Как грубеют (в противоположность, сглаживаются), список в функциональном стиле?

Например, у меня есть список (1 2 3 4 5 6 7 8 9 10 11), и хочу придать шероховатость ему 3 элементами (или другая длина) для получения ((1 2 3) (4 5 6) (7 8 9) (10 11)). Какой симпатичный код я мог использовать для этого?Спасибо.

6
задан Ben Lings 20 May 2010 в 19:53
поделиться

7 ответов

List(1,2,3,4,5,6,7,8,9,10,11) grouped 3 toList

res0: List[List[Int]] = List(List(1, 2, 3), List(4, 5, 6), 
List(7, 8, 9), List(10, 11))
15
ответ дан 8 December 2019 в 02:21
поделиться

Поскольку вы тоже используете тег Clojure ...

В Clojure 1.2, также доступный в 1.1 в clojure.contrib.seq-utils.

(partition-all 3 [1 2 3 4 5 6 7 8 9 10 11])
; => ((1 2 3) (4 5 6) (7 8 9) (10 11))

См. Также раздел и разделение по . Также обратите внимание, что partition и partition-all принимают некоторые необязательные аргументы, если вам нужно что-то немного другое, см., Например, (раздел документа) в REPL.

15
ответ дан 8 December 2019 в 02:21
поделиться
def split[A](list : List[A], n : Int) : List[List[A]] = list match {
    case List() => List()
    case     _  => (list take n) :: split(list drop n, n)
}
2
ответ дан 8 December 2019 в 02:21
поделиться

И еще одна версия clojure, написанная на более идиоматическом clojure.

(defn roughen
  [n coll]
  (lazy-seq
    (when-let [s (seq coll)]
      (let [[l r] (split-at n s)]
        (cons l (roughen n r))))))

Обратите внимание, что split-at дважды проходит входную последовательность. Таким образом, вы можете заменить стандартную версию следующей:

(defn split-at
  [n coll]
  (loop [n n, s coll, l []]
    (if-not (zero? n)
      (if-let [s (seq s)]
        (recur (dec n) (rest s) (conj l (first s)))
        [l nil])
      [l s])))

(Конечно, можно было бы использовать раздел и друзей, как уже упоминалось выше.)

2
ответ дан 8 December 2019 в 02:21
поделиться

Это лучшее, что я мог придумать:

def roughen(l:List[_],s:Int):List[_] ={

  if (l.isEmpty) return Nil
  val l2 = l.splitAt(s)
  l2._1 :: roughen(l2._2,s)

}

val l = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
roughen(l,3)
//returns: List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9), List(10))
1
ответ дан 8 December 2019 в 02:21
поделиться

Вот реализация roughen, совместимая с Clojure 1.0:

(defn roughen
  "Roughen sequence s by sub-grouping every n elements.
   e.gn (roughen '(a b c d) 2) -> ((a b) (c d))"
  [s n]
  (loop [result () s s]
    (cond (empty? s)
      result
      (< (count s) n)
      (concat result (list s))
      :default
      (recur (concat result (list (take n s))) (drop n s)))))

user=> (roughen '(a b c d e f g) 2)
((a b) (c d) (e f) (g))
user=> (roughen '(a b c d e f) 2)
((a b) (c d) (e f))
user=> (roughen '(a b c d e f) 4)
((a b c d) (e f))
user=> 
1
ответ дан 8 December 2019 в 02:21
поделиться

В Scala 2.8 List смешивается с IterableLike, у которого есть сгруппированный метод, который возвращает Iterator [List [T]], который, в свою очередь, может быть преобразован в List [List [T]].

List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11).grouped(3).toList

res3: List[List[Int]] = List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9), List(10, 11))

Если вам нужен грубый метод в List, вы можете использовать неявное преобразование, например:

scala> class RList[T](val l: List[T]) {def roughen(n: Int) = l.grouped(n).toList}
defined class RList

scala> implicit def list2rlist[T](l: List[T]) = new RList(l)
list2rlist: [T](l: List[T])RList[T]    

scala> List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) roughen 3
res5: List[List[Int]] = List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9), List(10, 11))
3
ответ дан 8 December 2019 в 02:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: