Рубиновый способ группировки анаграмм в строковом массиве - PullRequest
7 голосов
/ 10 марта 2012

Я реализовал функцию группировки анаграмм.Вкратце:

ввод: ['cars', 'for', 'potato', 'racs', 'four', 'scar', 'creams', scream ']

вывод: [["cars", "racs", "scar"], ["four"], ["for"], ["potato"], ["creams", "scream"]]

Я хотел бы знать, есть ли лучший способ сделать это.Я действительно думаю, что использовал слишком много повторений: until, select, delete_if.Есть ли способ объединить операторы select и delete_if?Это значит, можно ли автоматически удалять выбранные элементы?

Код:

def group_anagrams(words)
  array = []
  until words.empty? 
    word = words.first
    array.push( words.select { |match| word.downcase.chars.sort.join.eql?(match.downcase.chars.sort.join ) } )
    words.delete_if { |match| word.downcase.chars.sort.join.eql?(match.downcase.chars.sort.join ) }
  end
  array
end

Заранее спасибо,

Ответы [ 2 ]

34 голосов
/ 10 марта 2012

Вот так:

 a = ['cars', 'for', 'potatoes', 'racs', 'four','scar', 'creams', 'scream']
 a.group_by { |element| element.downcase.chars.sort }.values

Вывод:

[["cars", "racs", "scar"], ["for"], ["potatoes"], ["four"], ["creams", "scream"]]

Если вы хотите, вы можете превратить эту однострочную в метод курса.

0 голосов
/ 10 марта 2012

Вы можете использовать функцию partition вместо select, реализованную в Enumerable . Он разделяет записи в массиве согласно решающей функции на два массива.

def group_anagrams(words)
  array = []
  until words.empty? 
    word = words.first
    delta, words = words.partition { |match| word.downcase.chars.sort.join.eql?(match.downcase.chars.sort.join ) } )
    array += delta
  end
  array
end

(непроверенные)

...