2015-07-15 7 views
1

Я хочу сортировать массив массивов строк первой строкой, пропуская первый массив, но у меня просто нет идеи, как это сделать, используя встроенную команду sort метод. Я мог бы скопировать весь массив без первого элемента и отсортировать возвращаемый массив, но нет ли более элегантного способа сделать это?Ruby: Сортировка массива, пропуская первый элемент

ar = [["zzzz", "skip", "this"], ["EFP3","eins","eins"], ["EFP10","zwei","zwei"], ["EFP1","drei","drei"]] 
ar.sort!{ |a,b| 
    if a == ar.first # why doesn't 
    next    # this 
    end    # work ? 

    # compare length, otherwise it would be e.g. 10 < 3 
    if a[0].length == b[0].length 
    a[0] <=> b[0] 
    else 
    a[0].length <=> b[0].length 
    end 
} 

Я хочу, чтобы иметь результат, как этот:

["zzzz", "skip", "this"], ["EFP1","drei","drei"], ["EFP3","eins","eins"], ["EFP10","zwei","zwei"] 

sortet по "EFP#"

редактирования: Я использую Ruby 1.8, если это важно.

ответ

2

Вы можете сделать это следующим образом:

[ar.first] + ar[1..-1].sort{ |a,b| a[0] <=> b[0] } 
# => [["zzzz", "skip", "this"], ["EFP1", "drei", "drei"], ["EFP10", "zwei", "zwei"], ["EFP3", "eins", "eins"]] 
1

Другие объяснили, как получить правильный ответ.

Что касается того, почему это не работает, сортировка просто не ожидает «следующего». «next» - это языковая конструкция, предназначенная для нормального цикла. sort, однако, является функцией, которая неоднократно запрашивает другую функцию для результата. Как обычная функция Ruby, она не может определить, вернулась ли вы «следующая», потому что это эквивалент возвращаемого нуля (или оставление тела пустым). И поэтому он не может иметь и не имеет каких-либо соглашений о том, как обрабатывать «следующий» экземпляр.

Это вызывает ошибку, поскольку nil не является допустимым числом для возврата из | a, b | сравнение.

2

но нет ли более элегантного способа сделать это?

Вы можете sort другие элементы и повторно assign их:

ar = [5, 4, 3, 2, 1] 

ar[1..-1] = ar[1..-1].sort 

ar #=> [5, 1, 2, 3, 4] 

Я хочу, чтобы результат [...] sortet по "EFP#"

sort_by выглядит правый инструмент:

ar = [["zzzz", "skip"], ["EFP3", "eins"], ["EFP10", "zwei"], ["EFP1", "drei"]] 

ar[1..-1] = ar[1..-1].sort_by { |s, _| s[/\d+/].to_i } 

ar #=> [["zzzz", "skip"], ["EFP1", "drei"], ["EFP3", "eins"], ["EFP10", "zwei"]] 

s[/\d+/].to_i извлекает цифры от s и преобразует его в целое число:

"EFP1"[/\d+/].to_i #=> 1 
"EFP3"[/\d+/].to_i #=> 3 
"EFP10"[/\d+/].to_i #=> 10 
0

сравнение возвращает -1, 0 или 1, так что если вы возвращать 1 для первого сортируется в качестве первого элемента, а 1 он станет последним элементом.

ar.sort!{ |a,b| 
    if a == ar.first 
    -1 
    elsif a[0].length == b[0].length # compare length, otherwise it would be e.g. 10 < 3 
    a[0] <=> b[0] 
    else 
    a[0].length <=> b[0].length 
    end 
} 

#=>[["zzzz", "skip", "this"], ["EFP1", "drei", "drei"], ["EFP3", "eins", "eins"], ["EFP10", "zwei", "zwei"]] 

 Смежные вопросы

  • Нет связанных вопросов^_^