Как отфильтровать список в J?
-
30-09-2019 - |
Вопрос
В настоящее время я изучаю увлекательный язык J-программирования, но одна вещь, которую я не смог понять, - это то, как отфильтровать список.
Предположим, у меня есть произвольный список 3 2 2 7 7 2 9
И я хочу удалить 2s, но оставьте все остальное без изменений, то есть мой результат будет 3 7 7 9
. Отказ Как на земле я это делаю?
Решение
Короткий ответ
2 (~: # ]) 3 2 2 7 7 2 9
3 7 7 9
Длинный ответ
У меня есть ответ для вас, но прежде чем вы познакомитесь с некоторыми деталями. Вот так.
Монады, двоиды
Есть два типа глаголы в J: монадс а также диода. Отказ Первый принять только один параметр, последний принимает два параметра.
Например, прохождение единоличного аргумента для монадический глагол #
, называется вполне, считает количество элементов в списке:
# 3 2 2 7 7 2 9
7
Глагол #
, который принимает два аргумента (слева и справа), называется скопировать, это дьядический И используется для копирования элементов из правильного списка столько раз, как указано в соответствующих элементах в левом списке (также может быть единственным элементом в списке):
0 0 0 3 0 0 0 # 3 2 2 7 7 2 9
7 7 7
Вилка
Есть понятие вилка В j, который представляет собой серию из 3 глаголов, применяемых к их аргументам, диадико или вновственно.
Вот диаграмма своего рода вилка Я использовал в первом фрагменте:
x (F G H) y
G
/ \
F H
/ \ / \
x y x y
Он описывает порядок, в котором глаголы применяются к их аргументам. Таким образом, эти приложения происходят:
2 ~: 3 2 2 7 7 2 9
1 0 0 1 1 0 1
То ~:
(не равно) дьядический В этом примере и приводит к списку логических значений, которые верны, когда аргумент не равен 2
. Отказ Это было F
Приложение в соответствии с диаграммой.
Следующее приложение H
:
2 ] 3 2 2 7 7 2 9
3 2 2 7 7 2 9
]
(личность) может быть монад или а диориада, но он всегда возвращает правильный аргумент, переданный на глагол (есть противоположный глагол, [
Что возвращается .. Да, левый аргумент! :)
Все идет нормально. F
а также H
После того, как приложение вернуло эти значения соответственно:
1 0 0 1 1 0 1
3 2 2 7 7 2 9
Единственный шаг для выполнения - это G
Приложение глагола.
Как я отметил ранее, глагол #
, который дьядический (Принимает два аргумента), позволяет нам дублировать элементы из правильного аргумента столько раз, как указано в соответствующих позициях в левом аргументе. Следовательно:
1 0 0 1 1 0 1 # 3 2 2 7 7 2 9
3 7 7 9
Мы только что получили список отфильтрованы из 2
с.
Ссылка
Немного другой вид вилка, крюк и другие примита (включая вышеупомянутые) описаны в этих двух документах:
- Краткая ссылка на J (175 киб)
- Easy-J. Введение в самый замечательный язык в мире программирования в мире (302 киб)
Другие полезные источники информации являются Jsoftware сайт с участием их вики И несколько архивов по почте в Интернете.
Другие советы
Просто чтобы убедиться, что это ясно, прямой путь - ответить на оригинальный вопрос - это:
3 2 2 7 7 2 9 -. 2
Это возвращает
3 7 7 9
Чем более сложный метод - генерируя логическое значение и использование его для сжимания вектора - больше апланета.
Чтобы ответить на другой вопрос в очень длинном посте, чтобы вернуть первый элемент и количество раз возникает, просто это:
({. , {. +/ .= ]) 1 4 1 4 2 1 3 5
1 3
Это вилка, использующая «{». Чтобы получить первый элемент, «{. + /. =]», чтобы добавить количество раз, первый элемент равен каждому элементу, а «», как средний глагол для объединения этих двух частей.
Также:
2 ( -. ~ ]) 3 2 2 7 7 2 9
3 7 7 9
Есть миллион способов сделать это - он беспокоит меня, смутно, что эти эти вещи не оценивают строго вправо налево, я старый программист APL, и я думаю о вещах вправо влево, даже когда они не Отказ
Если бы это было то, что я собирался вставить в программу, где я хотел вытащить какой-то номер, и число было постоянным, я бы сделал следующее:
(#~ 2&~:) 1 3 2 4 2 5
1 3 4 5
Я думаю, это крючок, я думаю. Правая половина выражения выражения генерирует вектор истины, в отношении которого не 2, а затем октуторп слева, имеет свои аргументы, поменяемые так, чтобы вектор истины - это левый аргумент для копирования, и вектор - это правильный аргумент. Я не уверен, что крючок быстрее или медленнее, чем вилка с копией аргумента.
+/3<+/"1(=2&{"1)/:~S:_1{;/5 6$1+i.6
156
Это выше программа отвечает на вопрос, «для всех возможных комбинаций yatzee Dice, сколько у 4 или 5 соответствующих номеров в одном ролике?» Он генерирует все перестановки, в коробках, сортирует каждую коробку индивидуально, распаковки их в качестве побочного эффекта, а также извлекает столбец 2, сравнивая коробку против собственного столбца 2, в единственном успешном вилке или крючке, которому мне удалось написать. Теория заключается в том, что если есть номер, который появляется в списке 5, трех или более раз, если вы сортируете список, среднее число будет тем, которое появляется с наибольшей частотой. Я предпринял попытку ряд других крючков и / или вилок, и каждый потерпел неудачу, потому что есть что я просто не получаю. Во всяком случае, эта таблица правды сводится к вектору, и теперь мы точно знаем, сколько раз каждая группа из 5 кубиков соответствовала среднему номеру. Наконец, этот номер сравнивается с 3, и количество успешных сравнений (больше 3, то есть 4 или 5).
Эта программа отвечает на вопрос: «Для всех возможных 8 цифрных номеров, сделанных из символов с 1 по 5, с повторением, сколько делится на 4?»
Я знаю, что вам нужно только определить, сколько в течение первых 25 делится на 4 и умножить, но программа работает более или менее мгновенно. В какой-то момент у меня была гораздо более сложная версия этой программы, которая создала номера в базе 5, так что отдельные цифры были от 0 до 4, добавлено 1 к тем, что генерируется цифр, а затем поместите их в базу 10. Это было что-то вроде 1+(8$5)#:i.5^8
+ / 0 = 4 |, (8 $ 10) #. > {; / 8 5 $ 1 + I.5 78125 Пока у меня есть исключительно глагольные поезда и выбор, у меня нет проблем. Когда я начинаю повторять свой аргумент в глаголе, чтобы я вынужден использовать вилки и крючки, которые я начинаю терять.
Например, вот что-то я не могу работать.
((1&{~+/)*./\(=1&{))1 1 1 3 2 4 1
Я всегда получаю индексную ошибку.
Точка состоит в том, чтобы вывести два числа, то же самое, что является первым числом в списке, второй, который совпадает с количеством раз, когда число повторяется.
Так что это много работает:
*./\(=1&{)1 1 1 3 2 4 1
1 1 1 0 0 0 0
Я сравниваю первый номер против остальной части списка. Затем я делаю вставку и сжатие - и это дает мне 1, пока у меня есть непрерывная строка из 1-х годов, как только она сломает и терпит неудачу, а нули вышли.
Я подумал, что я мог бы добавить еще один набор друзей, снова получить свинцовый элемент из списка, и как-то записывает эти цифры, возможная идея будет иметь еще одну стадию, где я прилагаю обратную версию вектора в исходный список, и Затем используйте $: чтобы вернуться к рекурсивному применению того же глагола. Вроде как быстрый пример, который я подумал, что я понял, но я думаю, что нет.
Но я даже не могу приблизиться. Я попрошу это как отдельный вопрос, чтобы люди получали должный кредит на ответ.