Как создать подмассив данного массива двоичных чисел, основанный на числе 1 в Ruby?
Пример:
Вот массив двоичных чисел:
a = [001, 010, 100, 011, 101, 110, 111, 1000, 1001, 1010]
Я хочу вывод, как показано ниже:
[ [ 001, 010, 100, 1000 ], [ 011, 101, 110, 1001, 1010 ], [ 111 ] ]
Кто-нибудь может мне помочь, как добиться этого в ruby?
2 ответа
Я собираюсь предположить, что вы работаете со строками ("001"
) а не десятичные / восьмеричные литералы (001
). Если это не так, я настоятельно рекомендую приводить строки, чтобы вам было легче.
Мы можем посчитать количество единиц в строке x
с x.count('1')
, Затем мы можем взять список строк и организовать его по этому значению с помощью a.group_by(...)
, Это дает хэш, поэтому, если вы просто хотите получить значения (как предполагает ваш предложенный вывод), тогда вы просто берете values
этого
a.group_by { |x| x.count('1') }.values
С помощью Enumerable#group_by
Как это сделал @Silvio, кажется, что это самый прямой способ решения этой проблемы, но здесь есть несколько других подходов, которые можно использовать.
a = "001, 010, 100, 011, 101, 110, 111, 1000, 1001, 1010".split(', ')
#=> ["001", "010", "100", "011", "101", "110", "111", "1000", "1001", "1010"]
Создайте хеш, ключи которого, k
, являются числами единиц и значениями которых являются массивы, содержащие элементы из исходного массива, чьи числа равны 1 k
a.each_with_object({}) { |s,h| (h[s.count('1')] ||= []) << s }.values
#=> [["001", "010", "100", "1000"], ["011", "101", "110", "1001", "1010"], ["111"]]
Заметка values
применяется к хешу, возвращенному блоком, а именно
{1=>["001", "010", "100", "1000"], 2=>["011", "101", "110", "1001", "1010"], 3=>["111"]}
Рассмотрим выражение, (h[s.count('1')] ||= []) << s
, Позволять
cnt = s.count('1')
затем (h[cnt] ||= []) << s
расширяется до следующего при разборе.
(h[cnt] = h[cnt] || []) << s
Если h
не имеет ключа cnt
, затем h[cnt]
на праве равенства равен nil
, так что выражение сводится к
(h[cnt] = []) << s
так h[cnt] #=> [s]
, С другой стороны, если h
есть ключ cnt
, h[cnt]
равен массиву, который является правдивым, поэтому мы выполняем
h[cnt] << s
Обратите внимание, что в h[cnt] = h[cnt] || []
, метод слева от равенства - Hash#[] =, тогда как у нас есть Hash#[] - справа от равенства.
Сортировать потом нарезать
a.sort_by { |s| s.count('1') }.slice_when { |s1,s2| s1.count('1') < s2.count('1') }.to_a
#=> [["001", "010", "100", "1000"], ["011", "101", "110", "1001", "1010"], ["111"]]