2017-02-13 4 views
2

У меня есть списокКак я могу перечислить список в эликсире?

[1, 4, 3] 

Я хочу, чтобы умножить его, что-то вроде:

[1, 4, 3] * 3 # => [1, 4, 3, 1, 4, 3, 1, 4, 3] 

Как я могу это сделать?

+0

Пожалуйста upvote ответ на Dogbert, то есть) быстрее, и б) приносит намного больше значения, чем моя глупая ссылка на документации. – mudasobwa

ответ

7

Я считаю, идиоматическое решение Elixir будет использовать List.duplicate/2

list |> List.duplicate(3) |> List.flatten 

Обратите внимание, что если ожидается, что в list есть вложенные списки, и они не должны быть уплощен, следует использовать:

list |> List.duplicate(3) |> :lists.concat 

- кредиты идут на @Dogbert

+0

Если вы просто замените 'List.flatten' на': lists.concat', вы получите самое быстрое решение в этом потоке (контрольный показатель в моем ответе). +1 для 'List.duplicate/2'. – Dogbert

+0

@ Dogbert Честно говоря, это «самый быстрый» в пределах стандартного интервала отклонений :) Я оставил бы этот ответ неповрежденным для формулировки «идиоматический». В «нашем» ответе я бы пошел с ': lists.concat (: lists.duplicate (@list, 100)) ', чтобы сохранить его, скажем, в одном синтаксисе. – mudasobwa

+0

Да, скорость в значительной степени идентична моей лучшей, но 'List.duplicate', безусловно, более идиоматична, чем' Enum.map' здесь. – Dogbert

0

Простейшая вещь, которая приходит на ум:

def multiply_list(list, factor) do 
    Enum.reduce(1..factor, [], fn(_, acc) -> acC++ list end) 
end 
+0

А как насчет моего ответа? – radubogdan

3

Я хотел бы использовать Stream.cycle/1

iex> stream = Stream.cycle([1, 4, 3]) 
iex> Enum.take(stream, 9) 
[1, 4, 3, 1, 4, 3, 1, 4, 3] 
+0

Это правильный способ сделать это. – mudasobwa

+0

@ mudasobwa Что случилось с моим решением? – asiniy

+0

@asiniy в этом надуманном примере нет ничего плохого; но это решение лениво и легко распараллеливается из коробки. – mudasobwa

5

Я хотел бы использовать Enum.map с :lists.concat (Enum.concat гораздо медленнее, чем :lists.concat):

:lists.concat(Enum.map(1..100, fn(_) -> @list end)) 

некоторые ориентиры для предложений в этой теме, и некоторые из моих попыток:

defmodule BasicBench do 
    use Benchfella 

    @list Enum.to_list(1..100) 

    bench "1 by @asiniy" do 
    Enum.reduce(1..100, [], fn(_, acc) -> acC++ @list end) 
    end 

    bench "2 by @radubogdan" do 
    Enum.take(Stream.cycle(@list), 10000) 
    end 

    bench "3 by @Dogbert" do 
    Enum.flat_map(1..100, fn(_) -> @list end) 
    end 

    bench "4 by @Dogbert" do 
    Enum.concat(Enum.map(1..100, fn(_) -> @list end)) 
    end 

    bench "5 by @Dogbert" do 
    :lists.concat(Enum.map(1..100, fn(_) -> @list end)) 
    end 

    bench "6 by @mudasobwa" do 
    @list |> List.duplicate(100) |> List.flatten 
    end 

    bench "7 by @mudasobwa + @Dogbert" do 
    :lists.concat(List.duplicate(@list, 100)) 
    end 
end 

Выход:

benchmark name    iterations average time 
7 by @mudasobwa + @Dogbert  50000 35.72 µs/op 
5 by @Dogbert     50000 38.92 µs/op 
6 by @mudasobwa     10000 124.30 µs/op 
3 by @Dogbert     10000 174.63 µs/op 
4 by @Dogbert     10000 242.24 µs/op 
2 by @radubogdan     2000 924.04 µs/op 
1 by @asiniy      1000 2143.24 µs/op 
+0

Не стесняйтесь предлагать больше способов, и я добавлю их в тесты. – Dogbert

+0

'@list |> List.duplicate (100) |> List.flatten' – mudasobwa

+0

@mudasobwa добавлен! – Dogbert

Смежные вопросы