Создание дублирующихся элементов в массиве с использованием функций высшего порядка - PullRequest
0 голосов
/ 25 октября 2018

Новый язык D здесь.Я пытаюсь использовать функции более высокого порядка (т.е. сложить! Уменьшить !, фильтр !, карту!) Для создания дубликатов элементов массива.Я объявляю свою общую функцию как чистую и пытаюсь выполнить эту задачу как однострочную функцию.Самое близкое, что я дошел, это

auto dupList(T)(T[] list) pure { (return map!(a => a.repeat(2)); }

, но это дает мне следующий вывод

[[1,1],[2,2]]

вместо того, что я на самом деле хочу

[1, 1, 2, 2]

Я вызываю функцию примерно так

writeln(dupList(nums));

Вместо использования карты я пытался использовать вместо нее сокращение, но когда я отключаю карту для уменьшения, я получаю следующие ошибки:

Error instantiated from here: `staticMap!(ReduceSeedType, __lambda2)` C:\D\dmd2\src\phobos\std\algorithm\iteration.d 3287
Error: template `D_Programs.duplist!int.duplist.__lambda2` cannot deduce function from argument types `!()(int, int)`, candidates are:  C:\D\dmd2\src\phobos\std\algorithm\iteration.d 3696
Error: template instance `D_Programs.duplist!int.duplist.F!(__lambda2)` error instantiating     C:\D\dmd2\src\phobos\std\meta.d 803
Error instantiated from here: `reduce!(int[])` D_Programs.d (refers to dupList)
Error `D_Programs.duplist!int.duplist.__lambda2` D_Programs.d (refers to dupList)
Error instantiated from here: `duplist!int` D_Programs.d (refers to where I'm calling from)

Буду признателен за любую помощь / совет относительно понимания по крайней мере трех основных ошибок и того, где я ошибаюсь с моей функцией.

Ответы [ 2 ]

0 голосов
/ 26 октября 2018

map по существу заменяет каждый элемент результатом вызова переданной функции для этого элемента.Поскольку ваша функция возвращает массив из двух int с, результатом будет массив массивов, каждый элемент содержит два int с.

Вооружившись этими знаниями, мы можем использовать std.algorith.iteration.joiner:

auto dupList(T)(T[] list) pure { return list.map!(a => a.repeat(2)).joiner; }

Как вы заметили, можно также использовать reduce, но это немного сложнее:

auto dupList(T)(T[] list) pure { return reduce!((a,b) => a~b~b)((int[]).init, list); }

Причины сложнееявляются:

1) Функция reduce принимает два аргумента - результат сокращения до настоящего времени и следующий элемент.

2) reduce предполагает, что первый элемент переданного массива является начальной точкой для сокращения, если не передано начальное значение.Поскольку первый элемент - int, а не int[], нам нужно будет передать начальное значение.[] не подойдет, так как он напечатан как void[], поэтому нам нужно создать пустой int[].Это можно сделать либо с помощью new int[0], либо, как указано выше, (int[]).init.

Надеюсь, это поможет - если есть еще вопросы, задавайте!:)

0 голосов
/ 26 октября 2018

Я предполагаю, что вы хотели вызвать map!(a => a.repeat(2))(list) или list.map!(a=>a.repeat(2)) (оба одинаковы), поскольку, если вы не передадите фактический список функции, он никогда не будет вызван!

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

Но сначала отступление: ваш призыв к сокращению не скомпилируется, потому что ему передаются неверные аргументы (или что-то подобное, сообщения об ошибкахдействительно плохи и их трудно читать, не имея кода, на который они ссылаются напрямую, но это определенно относится к лямбде).Передав это, ваш dupList не будет работать, потому что dupList принимает массив, но сокращение работает только с двумя элементами одновременно, например, sum(a, b).

В любом случае, вернемся к основной точке,самое близкое, что вы можете получить, это, возможно, запустить другую функцию вне карты, чтобы сгладить результирующий массив, или, другими словами, объединить их вместе.Для этого есть функция: http://dpldocs.info/experimental-docs/std.algorithm.iteration.joiner.2.html

Предложить возможный ответ:

    return list .map!(a => a.repeat(2)) .joiner;

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

    return
            list
                    .map!(a => a.repeat(2))
                    .joiner
            ;

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

...