Использование фильтра по векторам

Я пытаюсь использовать filter функция над вектором под названием dataset это определяется так:

AK,0.89,0.98
AR,0.49,0.23
AN,0.21,0.78
...

И я хочу получить все значения, которые содержат определенную строку, что-то вроде этого:

(filter (contains "AK") dataset)

Который вернется:

AK,0.89,0.98

Возможно ли это сделать с помощью функции фильтра? Я уже перебираю вектор, используя доза, но мне нужно использовать filter в какой-то момент в моем коде. Спасибо:)

1 ответ

Решение

Основной ответ - да, вы можете использовать фильтр, чтобы сделать это. Фильтр ожидает функцию предиката, т.е. функцию, которая возвращает истину или ложь. Функция фильтра перебирает элементы в коллекции, которую вы передаете, и передает каждый элемент из этой коллекции в предикат. То, что вы делаете внутри функции предиката, полностью зависит от вас (хотя вы должны избегать побочных эффектов). Фильтр соберет все элементы, где предикат вернул true, в новую ленивую последовательность.

По сути, у вас есть (полная форма)

(filter (fn [element] 
         ; some test returning true/fals) col)

где col ваша коллекция. Результатом будет LAZY SEQUENCE элементов, где функция предиката вернула true. Важно понимать, что такие вещи, как фильтр и карта, возвращают ленивые последовательности и знают, что это на самом деле означает.

Критическим моментом для понимания является структура вашей коллекции. В своем описании вы указали

Я пытаюсь использовать функцию фильтра для вектора под названием набор данных, который определен так:

AK, 0,89,0,98 AR,0,49,0,23 AN,0,21,0,78 ...

К сожалению, ваше описание немного двусмысленно. Если ваша структура набора данных на самом деле является вектором векторов (а не просто вектором), то все очень просто. Это потому, что это будет означать, что каждый "элемент", переданный в функцию предиката, будет одним из ваших "внутренних" векторов. Настоящее определение более точно представлено как

[
 [AK,0.89,0.98]
 [AR,0.49,0.23]
 [AN,0.21,0.78]
 ...
]

то, что будет передано предикату, является вектором из 3 элементов. Если вы просто хотите выбрать все векторы, где первым элементом является "AK", то функция предиката может быть такой простой, как

(fn [el]
 (if (= "AK" (first el))
   true;
   false))

Таким образом, полная строка будет что-то вроде

(filter (fn [el]
         (if (= "AK" (first el))
           true
           false)) [[AK 0.89 0.98] [AR 0.49 0.23] [AN 0.21 0.78]])

и это только начало и очень многословная версия. Вы можете сделать многое, чтобы сделать это еще короче, например

(filter #(= "AK" (first %)) [..])

Если, с другой стороны, у вас действительно есть только один вектор, то все становится немного сложнее, потому что вам нужно как-то сгруппировать значения. Это можно сделать с помощью функции разбиения, чтобы разбить ваш вектор на группы по 3 элемента, прежде чем передать их для фильтрации, например:

(filter pred (partition 3 col))

который сгруппировал бы элементы в вашем исходном векторе в группы по 3 и передал бы каждую группу функции предиката. Вот тут-то и вступает в действие реальная мощь карт, фильтров, сокращений и т. Д. - вы можете преобразовывать данные, передавая их через конвейер функций, каждая из которых каким-то образом манипулирует данными, и в результате появляется конечный результат.

Ключевым моментом является понимание того, что фильтр (и другие подобные функции, такие как map или Reduce) будут понимать как "элемент" в вашей коллекции входных данных. По сути, это то же самое, что будет возвращено "первым", вызванным в коллекции. Это то, что передается функции предиката в fileter.

Здесь много предположений. Одним из основных является то, что ваши данные строго упорядочены, т.е. значение, которое вы хотите проверить, всегда является первым элементом в каждой группе. Если это не так, то нужно будет проделать дополнительную работу. Аналогично, мы предполагаем, что данные всегда находятся в группах по 3. Если это не так, тогда потребуются другие подходы.

Другие вопросы по тегам