Как создать подмассив данного массива двоичных чисел, основанный на числе 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"]]
Другие вопросы по тегам