Группировать список строк по первым n буквам - PullRequest
1 голос
/ 27 марта 2019

У меня есть коллекция строк типа

["snowy10" "catty20" "manny20" "snowy20" "catty10" "snowy20" "catty30" "manny10" "snowy20"  "manny30"]

Хотелось бы преобразовать его в коллекцию коллекций, сгруппированных по первым пяти символам строки.

[["snowy10" "snowy20" "snowy20"] ["catty10" "catty20""catty30"]["manny10" ""manny20""  "manny20"]]

Ищем решение в Clojure.

Ответы [ 3 ]

5 голосов
/ 28 марта 2019

Функция group-by полезна здесь:

clojure.core/group-by
([f coll])
  Returns a map of the elements of coll keyed by the result of
  f on each element. The value at each key will be a vector of the
  corresponding elements, in the order they appeared in coll.

Другими словами, group-by использует данную функцию f для создания ключа для каждого элемента в coll, а значение, связанное с этим ключом, является вектором накопленных элементов для этого ключа.

В вашем примере, если мы знаем, что все входные строки гарантированно содержат не менее 5 символов, мы можем использовать subs. Но проще построить надежное решение, более общее с использованием take:

(def strings ["snowy10" "catty20" "manny20" "snowy20" "catty10" "snowy20" "catty30" "manny10" "snowy20"  "manny30"])

(group-by (partial take 5) strings)

дает нам:

{(\s \n \o \w \y) ["snowy10" "snowy20" "snowy20" "snowy20"]
 (\c \a \t \t \y) ["catty20" "catty10" "catty30"]
 (\m \a \n \n \y) ["manny20" "manny10" "manny30"]}

Это не совсем то, что мы хотим - мы просто хотим значения карты. Для этого мы используем vals:

(-> (group-by (partial take 5) strings)
    (vals))

и мы получаем:

(["snowy10" "snowy20" "snowy20" "snowy20"]
 ["catty20" "catty10" "catty30"]
 ["manny20" "manny10" "manny30"])

Изменить критерии группировки так же просто, как изменить функцию «ключа», которую мы предоставляем, на group-by. Например, мы можем сгруппировать по последним двум символам в каждой строке, используя take-last:

(-> (group-by (partial take-last 2) strings)
    (vals))

, что дает:

(["snowy10" "catty10" "manny10"]
 ["catty20" "manny20" "snowy20" "snowy20" "snowy20"]
 ["catty30" "manny30"])
3 голосов
/ 27 марта 2019
user> (def v ["snowy10" "catty20" "manny20" "snowy20" "catty10" "snowy20" "catty30" "manny10" "snowy20"  "manny30"])
#'user/v

user> (vals (group-by #(subs % 0 5) v))
(["snowy10" "snowy20" "snowy20" "snowy20"]
 ["catty20" "catty10" "catty30"]
 ["manny20" "manny10" "manny30"])
1 голос
/ 28 марта 2019

как насчет разделения строки на \d, например:

user=> (def v ["snowy10" "catty20" "manny20" "snowy20" "catty10" "snowy20" "catty30" "manny10" "snowy20"  "manny30"])
#'user/v
user=> (vals (group-by #(first (clojure.string/split % #"\d")) v))
(["snowy10" "snowy20" "snowy20" "snowy20"] 
 ["catty20" "catty10" "catty30"] 
 ["manny20" "manny10" "manny30"])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...