Як розбити масив за допомогою nil як делімітатора?

Я шукаю метод перетворення:

[1,2,3,nil,4,5,nil,6,7,8,9] 

в:

[[1,2,3],[4,5],[6,7,8,9]]

Чи є вбудований спосіб це зробити в Ruby?

0
No. :-) Ви зацікавлені в найбільш простий, рубіподібний спосіб зробити це?
додано Автор Peter Alfvin, джерело

8 Відповіді

Я б користуюсь:

[1,2,3,nil,4,5,nil,6,7,8,9].slice_before{ |e| e.nil? }.map(&:compact)
=> [[1, 2, 3], [4, 5], [6, 7, 8, 9]]

slice_before is really powerful when you want to break an array into chunks, either by searching for a repeating pattern by passing in a regex, or something you can compute via the block. It's much too powerful to summarize right here so take time to read the documentation and play with the examples.

6
додано
slice_before - це один з тих маловідомих методів в Ruby, який я не помітив на деякий час, а потім перемістив пальмову передачу. Це виявилося неймовірно корисним для багато обробки текстів. Якщо у вас є файл повторюваних блоків, то це легко розділити на масиви шматків.
додано Автор the Tin Man, джерело
Добре (+1). І ... компактний :)
додано Автор lurker, джерело

Це має працювати:

array = [1,2,3,nil,4,5,nil,6,7,8,9]
array.inject([[]]) do |result, number|
  number ? result.last << number : result << []
  result
end

#=> [[1, 2, 3], [4, 5], [6, 7, 8, 9]]

Час пояснення :-)

  • inject починається з масиву, що містить порожній масив
  • для кожного елемента він перевіряє, чи він не має значення
  • , якщо це не так, він додає поточний номер до попереднього масиву
  • якщо це так, він створює новий пустий масив
  • все це під час оновлення результату, який є масивом масивів

-- EDIT --

Перевірка відповіді Давида Я перевірив реалізацію Rails цього:

def split(value = nil)
  using_block = block_given?

  inject([[]]) do |results, element|
    if (using_block && yield(element)) || (value == element)
      results << []
    else
      results.last << element
    end

    results
  end
end

Якщо ви пропустите реалізацію блоку, вона має точно таку ж структуру мого коду. Так! :)

4
додано
Я не знаю, чи це помилка чи функція, але провідний або прохідний nil в масиві призведе до виведення провідного або заглушене порожнього субару з таким підходом.
додано Автор Peter Alfvin, джерело
@JuLiu: Насправді треба, для цього ще секунду та багато іншого! Добре зроблено!
додано Автор Peter Alfvin, джерело
Для того, що це коштує, це дуже сильно відповідає застосуванню Rails масиву # split, модуль додаткової гнучкості Rails, на github.com/rails/rails/blob/…
додано Автор Peter Alfvin, джерело
це здорово! дуже дякую
додано Автор szymanowski, джерело
@PeterAlfvin, я щойно помітив таку саму річ, і я відчував гордість на секунду!
додано Автор Ju Liu, джерело
Так, я хотів про це під час кодування, і я переконався, що це особливість: якщо ми хочемо розділити масив з токеном, і цей токен трапляється на початку масиву, то ми знайшли першу послідовність , що, на жаль, є порожньою послідовністю. Я думаю, це має сенс! Крім того, це такий самий підхід, як String # split: "0abc0cdc" .split ("0") => ["", "abc", "cdc"]
додано Автор Ju Liu, джерело

Це має працювати:

array = [1,2,3,nil,4,5,nil,6,7,8,9]
array.inject([[]]) do |result, number|
  number ? result.last << number : result << []
  result
end

#=> [[1, 2, 3], [4, 5], [6, 7, 8, 9]]

Час пояснення :-)

  • inject починається з масиву, що містить порожній масив
  • для кожного елемента він перевіряє, чи він не має значення
  • , якщо це не так, він додає поточний номер до попереднього масиву
  • якщо це так, він створює новий пустий масив
  • все це під час оновлення результату, який є масивом масивів

- РЕДАГУВАТИ -

Перевірка відповіді Давида Я перевірив реалізацію Rails цього:

def split(value = nil)
  using_block = block_given?

  inject([[]]) do |results, element|
    if (using_block && yield(element)) || (value == element)
      results << []
    else
      results.last << element
    end

    results
  end
end

Якщо ви пропустите реалізацію блоку, вона має точно таку ж структуру мого коду. Так! :)

4
додано
Я не знаю, чи це помилка чи функція, але провідний або прохідний nil в масиві призведе до виведення провідного або заглушене порожнього субару з таким підходом.
додано Автор Peter Alfvin, джерело
@JuLiu: Насправді треба, для цього ще секунду та багато іншого! Добре зроблено!
додано Автор Peter Alfvin, джерело
Для того, що це коштує, це дуже сильно відповідає застосуванню Rails масиву # split, модуль додаткової гнучкості Rails, на github.com/rails/rails/blob/…
додано Автор Peter Alfvin, джерело
це здорово! дуже дякую
додано Автор szymanowski, джерело
@PeterAlfvin, я щойно помітив таку саму річ, і я відчував гордість на секунду!
додано Автор Ju Liu, джерело
Так, я хотів про це під час кодування, і я переконався, що це особливість: якщо ми хочемо розділити масив з токеном, і цей токен трапляється на початку масиву, то ми знайшли першу послідовність , що, на жаль, є порожньою послідовністю. Я думаю, це має сенс! Крім того, це такий самий підхід, як String # split: "0abc0cdc" .split ("0") => ["", "abc", "cdc"]
додано Автор Ju Liu, джерело
[1,2,3,nil,4,5,nil,6,7,8,9].split(nil)

Whoops array#split is a Rails method

2
додано
невизначений метод `split 'для [1, 2, 3, нуль, 4, 5, нуль, 6, 7, 8, 9]: масив
додано Автор lurker, джерело
WAT - Час розслідування того, що зробив О.О.
додано Автор David, джерело
LOL @ David :-D
додано Автор Ju Liu, джерело
Масиви не рядки :-)
додано Автор Ju Liu, джерело
[1,2,3,nil,4,5,nil,6,7,8,9].split(nil)

Whoops array#split is a Rails method

2
додано
невизначений метод `split 'для [1, 2, 3, нуль, 4, 5, нуль, 6, 7, 8, 9]: масив
додано Автор lurker, джерело
WAT - Час розслідування того, що зробив О.О.
додано Автор David, джерело
LOL @ David :-D
додано Автор Ju Liu, джерело
Масиви не рядки :-)
додано Автор Ju Liu, джерело

Я знайшов свого роду цікавий. Можливо, це спосіб скоротити його:

[1,2,3,nil,4,5,nil,6,7,8,9].chunk {|e| e.nil?}.select {|e| not e[0]}.flatten(1).delete_if {|e| not e}
1
додано
Корисно використовувати chunk , але краще використовувати nil і щось інше замість true і false . Наприклад: [1,2,3, нуль, 4,5, нуль, 6,7,8,9]. Чок (| e | : групується, якщо не є e.nil?}. map (&: last)
додано Автор Marc-André Lafortune, джерело
@ Марк-Андре Лаффут, дякую, гарна пропозиція. Я викачав з виходом за замовчуванням chunk , не надавши набагато більше уваги, з'ясувавши, що, мабуть, це був кращий спосіб. Ця нитка змусила мене відкрити кілька цікавих методів масиву Ruby. :)
додано Автор lurker, джерело

Я приєднався до масиву, а потім розділив масив.

a =[1,2,3,nil,4,5,nil,6,7,8,9] 

a = a.join("-").split("--")
a.map! { |a| a.split("-") }
a.map! {|e| e.map! {|f| f.to_i}}
puts a.inspect

#[[1, 2, 3], [4, 5], [6, 7, 8, 9]]

Зроблено редагування (на основі коментарів), щоб зробити це цілим числом ще раз. Хоча все-таки не хороша відповідь.

0
додано
Жахливі рішення, немає причин перетворювати елементи в рядки.
додано Автор Marc-André Lafortune, джерело
Хтось .. погана відповідь!
додано Автор Amey, джерело

Я приєднався до масиву, а потім розділив масив.

a =[1,2,3,nil,4,5,nil,6,7,8,9] 

a = a.join("-").split("--")
a.map! { |a| a.split("-") }
a.map! {|e| e.map! {|f| f.to_i}}
puts a.inspect

#[[1, 2, 3], [4, 5], [6, 7, 8, 9]]

Зроблено редагування (на основі коментарів), щоб зробити це цілим числом ще раз. Хоча все-таки не хороша відповідь.

0
додано
Жахливі рішення, немає причин перетворювати елементи в рядки.
додано Автор Marc-André Lafortune, джерело
Хтось .. погана відповідь!
додано Автор Amey, джерело