Эй, ребята, у меня вопрос. Я хочу преобразовать массив. [[1, [-1, 1]], [1, [20, 8]], [1, [30, 4]], [1, [40, 2]], [1, [41, 6]], [1, [70, 243]]]
в этот стиль [1,[[-1,1],[20,8],[30,4]...]
или хэш [1 => ...] Как я могу сделать этот трюк? Спасибо !Вопрос о рубине!
ответ
Dict метод:
array = [your array]
dict = {}
array.each{ |a| (dict[a[0]] ||= []) << a[1] }
Для внушения ясности Чака бы довести это до:
array = [your array]
dict = Hash.new {|h,k| h[k] = []}
array.each{ |a| dict[a[0]] << a[1] }
Вы можете получить массив из этого в стиле вы хотите, выполнив:
new_arr = dict.select{|k,v| [k, v]}
Что даст вам:
[[1, [[-1, 1], [20, 8], [30, 4], [40, 2], [41, 6], [70, 243]]]]
Обратите внимание на дополнительный массив, потому что, если у вас были массивы, начинающиеся с 2, у вас будет другой набор в конце. Итак, new_arr[0]
даст вам массив, который вы искали.
Вы можете сделать это:
array = [[1, [-1, 1]], [1, [20, 8]], [1, [30, 4]],
[1, [40, 2]], [1, [41, 6]], [1, [70, 243]]]
# map into hashes that can be merged together
hashes = array.map do |key,value|
{ key => [value] }
end
# fold all hashes into one hash by merging the values by key
merged_hash = hashes.inject({}) do |accu,value|
accu.merge!(value) {|_,o,n| o|n }
end
Это можно записать в виде не так легко однострочника:
array.map{|k,v|{k=>[v]}}.inject({}){|a,v|a.merge!(v){|_,o,n|o|n}}
#==> {1=>[[-1, 1], [20, 8], [30, 4], [40, 2], [41, 6], [70, 243]]}
Это кажется более сложным, чем решение Мэтта. Почему вы предпочитаете этот способ сделать это? – Chuck
@Chuck Решает проблему без загрязнения локального пространства имен переменных с помощью 'injection'. И я предпочитаю метод 'merge' над || = []. Конечно, это вопрос вкуса. Но я думаю, что решение Мэтта можно было бы переписать с помощью «инъекции», тем самым предотвратив загрязнение пространства имен с помощью temp vars. – hurikhan77
Если вы хотите как Hash
, это просто
h = Hash[ary.group_by(&:first).map {|k, v| [k, v.map(&:last)] }]
И если вы хотите, чтобы это было как Array
, вы просто конвертировали Hash
в a Array
:
a = *h
+1 для очень элегантного решения, но я хотел бы упомянуть, что group_by может не работать со старыми API-интерфейсами ruby. – hurikhan77
Я считаю, что '.group_by' - ruby 1.9, хотя может быть опция rails. –
Код запускается без изменений в Ruby 1.8.7 и новее. Чтобы использовать его в Ruby 1.8.6, вам потребуется потребовать backports для 'Enumerable # group_by' и' Symbol # to_proc'. – Chuck
- 1. вопрос о переопределении + оператор в рубине
- 2. Разнос вопрос в Рубине
- 3. Вопрос о рубиновой грамматике
- 4. Вопрос о
- 5. Вопрос о форме Silverlight Вопрос
- 6. Происходит ли заявление о рубине?
- 7. Заявление о рубине на хэш?
- 8. проблема о singleton в рубине
- 9. Вопросы о массивах в рубине
- 10. CSV вопрос кодирования файлов в рубине
- 11. Вопрос относительно переменной изменения в Рубине
- 12. Запрос о некоторых особенностях занятий в рубине
- 13. Вопрос о SQL-группировке
- 14. Вопрос о sys.argv (python)
- 15. Вопрос о строковых формах
- 16. Вопрос о Winforms
- 17. Вопрос о семафоре
- 18. Вопрос о peverify ошибок
- 19. Вопрос о конструкторе Singleton
- 20. Вопрос о взаимоотношениях дружбы
- 21. Вопрос о сокетах TCP
- 22. iPhone - вопрос о DrawRect
- 23. простой вопрос о pushViewController
- 24. Вопрос о кодировании JQuery?
- 25. Вопрос о кодировке Mysql
- 26. вопрос о горизонтальном выравнивании
- 27. CSS: вопрос о переключателе
- 28. вопрос о умных указателях
- 29. Вопрос о двойном лицензировании
- 30. 301 вопрос о переадресации?
Вы также можете легко получить эквивалентный массив таким образом. Создайте хэш, затем сделайте 'hash.map {| ключ, значения | [ключ, значения]} '. Кроме того, вы можете значительно упростить свой «каждый», создав хэш как «Hash.new {[]}» - тогда вам не нужно «|| = []» на каждой итерации, поскольку несуществующие ключи вернутся пустой массив. – Chuck
'Hash.new {[]}' будет работать только с операторами присваивания типа '+ =', но с '<<' он не будет. Я отредактировал ответ соответственно. –