Подтвердить что ты не робот

Какова функция выравнивания одноуровневой последовательности в Clojure?

Какова функция выравнивания одноуровневой последовательности в Clojure? Я использую apply concat пока, но мне интересно, есть ли для него встроенная функция, либо в стандартной библиотеке, либо в clojure -contrib.

4b9b3361

Ответ 1

Мой общий выбор - apply concat. Кроме того, не (for [subcoll coll, item subcoll] item) - в зависимости от более широкого контекста это может привести к более четкому коду.

Ответ 2

Нет стандартной функции. apply concat является хорошим решением во многих случаях. Или вы можете эквивалентно использовать mapcat seq.

Проблема с apply concat заключается в том, что она терпит неудачу, если на первом уровне есть что-то другое, кроме набора/последовательности:

(apply concat [1 [2 3] [4 [5]]])
=> IllegalArgumentException Don't know how to create ISeq from: java.lang.Long...

Следовательно, вы можете сделать что-то вроде:

(defn flatten-one-level [coll]  
  (mapcat  #(if (sequential? %) % [%]) coll))

(flatten-one-level [1 [2 3] [4 [5]]])
=> (1 2 3 4 [5])

Как более общий момент, отсутствие встроенной функции обычно не мешает вам определять свой собственный: -)

Ответ 3

Я тоже использую apply concat - я не думаю, что в ядре есть что-то еще.

flatten - несколько уровней (и определяется через древовидный переход, а не в виде повторного одноуровневого расширения)

см. также Clojure: полу-сглаживание вложенной последовательности, которая имеет flatten-1 из clojure mvc (и это намного сложнее, чем я ожидал).

обновить, чтобы прояснить лень:

user=> (take 3 (apply concat (for [i (range 1e6)] (do (print i) [i]))))
012345678910111213141516171819202122232425262728293031(0 1 2)

вы можете видеть, что он оценивает аргумент 32 раза - это chunking для эффективности, и в противном случае ленивый (он не оценивает весь список). для обсуждения chunking см. комментарии в конце http://isti.bitbucket.org/2012/04/01/pipes-clojure-choco-1.html