Соберите несколько значений в разных списках кортежа с помощью fold erlang

Мне нужно повторить последовательность, имеющую элементы в списке, например Sequence = ["1","2","4","5"]. Необходимо подготовить 9 списков, которые можно рассчитать только из Sequence. У меня есть следующая папка.

Accumulators = {[], [], [], [], [], [], [], [], []},
ReturnedTup = lists:foldl(fun(Seq, Acc) ->
       {AccF1,AccF2,AccF3, AccF4,AccF5,AccF6, AccF7,AccF8,AccF9} = Acc,
       F1 = get_seq_indexlist(Seq, "F1"),
       F2 = get_seq_indexlist(Seq, "F2"),
       F3 = get_seq_indexlist(Seq, "F3"),
       ...
       F9 = get_seq_indexlist(Seq, "F9"),
       [F1|AccF1], [F2|AccF2], [F3|AccF3], ...,[F9|AccF9],
       Acc      
     end, Accumulators, Sequence),
io:format("~p ReturnedTup", [ReturnedTup]).

Но здесь я получаю ReturnedTup пустым как {[], [], [], [], [], [], [], [], []}. Я не уверен, что в этом не так. Я получаю правильные значения в F1, F2, F3... F9.

Я новичок в эрланге. Там может быть эффективный способ сделать это. Если да, дайте мне знать.


person trex    schedule 19.09.2014    source источник


Ответы (2)


Ваша функция в foldl всегда возвращает исходный аккумулятор:

Acc

Вам нужно вернуть новый акк, который должен быть кортежем, содержащим обновленные списки.:

Accumulators = {[], [], [], [], [], [], [], [], []},
ReturnedTup = lists:foldl(fun(Seq, Acc) ->
       {AccF1,AccF2,AccF3, AccF4,AccF5,AccF6, AccF7,AccF8,AccF9} = Acc,
       F1 = get_seq_indexlist(Seq, "F1"),
       F2 = get_seq_indexlist(Seq, "F2"),
       F3 = get_seq_indexlist(Seq, "F3"),
       ...
       F9 = get_seq_indexlist(Seq, "F9"),
       {[F1|AccF1], [F2|AccF2], [F3|AccF3], ...,[F9|AccF9]}
     end, Accumulators, Sequence),
person Danil Onishchenko    schedule 19.09.2014

Ответ Резинового Ктулу только начинается :)

Хорошо бы убрать дублирование кода. Если вы копируете что-то девять раз - это сложно поддерживать.

Sequence = ["1","2","4","5"],
Accumulators = [[], [], [], [], [], [], [], [], []],
CounterToString = fun(Integer) -> "F"++integer_to_list(Integer) end,
FoldlFun = fun(SequenceElement, Acc) ->
                   PrependSeqIndexList = fun(Counter, InnerAcc) ->
                                                [get_seq_indexlist(SequenceElement, CounterToString(Counter)) | InnerAcc] end,
                   {NewAccs, _LastCounter} = lists:mapfoldl(fun(InnerAcc, Counter) ->
                                                                    {PrependSeqIndexList(Counter, InnerAcc),
                                                                     Counter+1} end, 1, Acc),
                   NewAccs
           end,
ReturnedList = lists:foldl(FoldlFun, Accumulators, Sequence),
ReturnedTup = list_to_tuple(ReturnedList),
io:format("~p ReturnedTup", [ReturnedTup]).
  • Я бы изменил Seq на SequenceElement, потому что функция, являющаяся аргументом foldl/3, принимает элемент последовательности, а не всю последовательность. Или вы можете назвать его InnerSequence - не имеет значения.
  • Вы хотите перебирать внутренние аккумуляторы, поэтому сделайте их списком
  • Используйте mapfoldl для перебора внутренних аккумуляторов — он работает как карта, но у него также есть аккумулятор, который мы будем использовать для счетчика.
  • Если вам действительно нужно возвращаемое значение в кортеже, используйте list_to_tuple/1 в конце
  • Назовите своих помощников, это облегчит чтение кода.
  • Если вы создаете забаву внутри другой забавы, вы можете использовать внешние аргументы забавы. PrependSeqIndexList использует SequenceElement, даже если он находится во внешней области. Это называется закрытием.
  • Есть и другие способы улучшить этот код — например, он по-прежнему глубоко вложен, но я оставлю это вам в качестве упражнения :)
person tkowal    schedule 19.09.2014