Как повторять отдельные символы в строках в Юлии - PullRequest
0 голосов
/ 27 сентября 2018

Этот вопрос показывает, как повторять отдельные символы в строках в Python.

>>> s = '123abc'
>>> n = 3
>>> ''.join([c*n for c in s])
'111222333aaabbbccc'

Как бы вы это сделали в Юлии?

РЕДАКТИРОВАТЬ

Будучи новичком в Юлии, я удивляюсь тому, что может предложить язык.

Например, я бы подумал, что приведенный выше код Python примерно такой же простой, как и кодполучить на любом языке.Однако, как показано в моем ответе ниже, код Джулии, эквивалентный join([c^n for c in s]), возможно, проще и может достигать оптимальности простоты для любого языка.

С другой стороны, @ niczky12 показал, что сдобавив оператор многоточия к функции string, можно существенно увеличить скорость по сравнению с тем, что достигается несколько более простой функцией join.

В одном случае Джулия сияет простотой.В другом случае Юлия сияет за скорость.

Для программистов на Python первый случай должен быть почти сразу же читаемым, когда они замечают, что c^n это просто c*n в Python.Когда они видят увеличение скорости с помощью оператора ... ellipsis, дополнительная сложность может не помешать им изучить Джулию.Читатели могут начать думать, что я надеюсь, что многие программисты на Python воспримут Джулию всерьез.Они не ошибутся.

Спасибо @ rickhg12hs за предложение о сравнительной оценке.Я многому научился.

Ответы [ 3 ]

0 голосов
/ 27 сентября 2018

Код протестирован в Version 1.0.0 (2018-08-08).

Когда я пытаюсь написать map(x -> x^3, "123abc"), у меня появляется ошибка.

julia> map(x -> x^3, "123abc")
ERROR: ArgumentError: map(f, s::AbstractString) requires f to return AbstractChar; try map(f, collect(s)) or a comprehension instead

Итак, есть другой способ сделать это.

julia> map(x -> x^3, collect("123abc"))
6-element Array{String,1}:
 "111"
 "222"
 "333"
 "aaa"
 "bbb"
 "ccc"

julia> join(map(x -> x^3, collect("123abc")))
"111222333aaabbbccc"

А может быть repeat удобнее.

julia> repeat(collect("123abc"), inner=3)
18-element Array{Char,1}:
 '1'
 '1'
 '1'
 '2'
 '2'
 '2'
 '3'
 '3'
 '3'
 'a'
 'a'
 'a'
 'b'
 'b'
 'b'
 'c'
 'c'
 'c'
julia> join(repeat(collect("123abc"), inner=3))
"111222333aaabbbccc"
0 голосов
/ 27 сентября 2018

В дополнение к ответам выше, я обнаружил, что функция string работает еще быстрее.Вот мои тесты:

julia> n = 2;

julia> s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

julia> string((c^n for c in s)...) # proof that it works
"AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXXYYZZ"

julia> n = 26000;

julia> @benchmark join(c^n for c in s)
BenchmarkTools.Trial:
  memory estimate:  1.44 MiB
  allocs estimate:  36
  --------------
  minimum time:     390.616 μs (0.00% GC)
  median time:      425.861 μs (0.00% GC)
  mean time:        484.638 μs (6.54% GC)
  maximum time:     45.006 ms (98.99% GC)
  --------------
  samples:          10000
  evals/sample:     1

julia> @benchmark string((c^n for c in s)...)
BenchmarkTools.Trial:
  memory estimate:  1.29 MiB
  allocs estimate:  31
  --------------
  minimum time:     77.480 μs (0.00% GC)
  median time:      101.667 μs (0.00% GC)
  mean time:        126.455 μs (0.00% GC)
  maximum time:     832.524 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

Как вы можете видеть, это примерно в 3 раза быстрее, чем решение join, предложенное @Julia Learner.Я протестировал выше на 0,7, но не было предупреждений об устаревании, поэтому я полагаю, что он работает хорошо на 1,0 тоже.Даже TIO так говорит .

0 голосов
/ 27 сентября 2018

Вы можете сделать это либо с помощью Julia, либо с помощью генератора.

julia> VERSION
v"1.0.0"

julia> s = "123abc"
"123abc"

# n is number of times to repeat each character.
julia> n = 3
3

# Using a Julia comprehension with [...]
julia> join([c^n for c in s])
"111222333aaabbbccc"

# Using a Julia generator without the [...]
julia> join(c^n for c in s)
"111222333aaabbbccc"

Для небольших струн практическая разница в скорости должна быть небольшой.

Редактировать

TL; DR: В общем, генератор несколько быстрее, чем понимание.Тем не менее, см. Случай 3 для противоположного.Оценки памяти были очень похожи.

@ rickhg12hs предположил, что было бы неплохо иметь тесты.

Используя отличный пакет BenchmarkTools, результаты ниже.

n = the number of times to repeat each character

s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" in each case

В каждом случае медианное время понимания C указывается первым, а медианное время генератора G - секунда.Времена были округлены, как казалось уместным, и оригинальные цифры ниже нумерованных сводок.Меньше, конечно, лучше.

Оценки памяти не сильно отличались.

1.n = 26, C = 3,8 против G = 2,8 мкс, G быстрее

julia> using BenchmarkTools

julia> n = 26;

julia> @benchmark join([c^n for c in s])
BenchmarkTools.Trial:
  memory estimate:  3.55 KiB
  allocs estimate:  39
  --------------
  minimum time:     3.688 μs (0.00% GC)
  median time:      3.849 μs (0.00% GC)
  mean time:        4.956 μs (16.27% GC)
  maximum time:     5.211 ms (99.85% GC)
  --------------
  samples:          10000
  evals/sample:     8

julia> @benchmark join(c^n for c in s)
BenchmarkTools.Trial:
  memory estimate:  3.19 KiB
  allocs estimate:  36
  --------------
  minimum time:     2.661 μs (0.00% GC)
  median time:      2.756 μs (0.00% GC)
  mean time:        3.622 μs (19.94% GC)
  maximum time:     4.638 ms (99.89% GC)
  --------------
  samples:          10000
  evals/sample:     9

2.n = 260, C = 10,7 против G = 8,1 мкс, G быстрее

julia> n = 260;

julia> @benchmark join([c^n for c in s])
BenchmarkTools.Trial:
  memory estimate:  19.23 KiB
  allocs estimate:  39
  --------------
  minimum time:     8.125 μs (0.00% GC)
  median time:      10.691 μs (0.00% GC)
  mean time:        18.559 μs (35.36% GC)
  maximum time:     43.930 ms (99.92% GC)
  --------------
  samples:          10000
  evals/sample:     1

julia> @benchmark join(c^n for c in s)
BenchmarkTools.Trial:
  memory estimate:  18.88 KiB
  allocs estimate:  36
  --------------
  minimum time:     7.270 μs (0.00% GC)
  median time:      8.126 μs (0.00% GC)
  mean time:        10.872 μs (18.04% GC)
  maximum time:     10.592 ms (99.87% GC)
  --------------
  samples:          10000
  evals/sample:     4

3.n = 2600, C = 62,3 против G = 63,7 мкс, C быстрее

julia> n = 2600; 

julia> @benchmark join([c^n for c in s])
BenchmarkTools.Trial:
  memory estimate:  150.16 KiB
  allocs estimate:  39
  --------------
  minimum time:     51.746 μs (0.00% GC)
  median time:      63.293 μs (0.00% GC)
  mean time:        77.315 μs (2.79% GC)
  maximum time:     3.721 ms (96.85% GC)
  --------------
  samples:          10000
  evals/sample:     1

julia> @benchmark join(c^n for c in s)
BenchmarkTools.Trial:
  memory estimate:  149.80 KiB
  allocs estimate:  36
  --------------
  minimum time:     47.897 μs (0.00% GC)
  median time:      63.720 μs (0.00% GC)
  mean time:        88.716 μs (17.58% GC)
  maximum time:     42.457 ms (99.83% GC)
  --------------
  samples:          10000
  evals/sample:     1

4.n = 26000, C = 667 против G = 516 мкс, G быстрее

julia> n = 26000; 

julia> @benchmark join([c^n for c in s])
BenchmarkTools.Trial:
  memory estimate:  1.44 MiB
  allocs estimate:  39
  --------------
  minimum time:     457.589 μs (0.00% GC)
  median time:      666.710 μs (0.00% GC)
  mean time:        729.592 μs (10.91% GC)
  maximum time:     42.673 ms (98.76% GC)
  --------------
  samples:          6659
  evals/sample:     1

julia> @benchmark join(c^n for c in s)
BenchmarkTools.Trial:
  memory estimate:  1.44 MiB
  allocs estimate:  36
  --------------
  minimum time:     475.977 μs (0.00% GC)
  median time:      516.176 μs (0.00% GC)
  mean time:        659.001 μs (10.36% GC)
  maximum time:     42.268 ms (98.41% GC)
  --------------
  samples:          7548
  evals/sample:     1
...