2013-05-28 3 views
2

Я хочу, чтобы преобразовать ABCDEF в A,B,C,D,E,FPerl: длинный перевод строки в разделенных запятыми список байт

Какой самый быстрый способ сделать это с помощью Perl ?

У меня есть много строк для преобразования, а строки могут быть длиной до 32768 байтов. Итак, я хочу снизить накладные расходы из преобразования строк.

ответ

8

Как насчет

$string =~ s/.\K(?=.)/,/g;  # using \K keep escape 
$string =~ s/(?<=.)(?=.)/,/g; # pure lookaround assertion 

Или

$string = join ",", split(//, $string); 

Чтобы найти быстрое решение, использовать Benchmark.

Дополнительный кредит:

Это результат теста я попробовал. Удивительно, но побег \K намного быстрее, чем чистый обход, который примерно так же быстро, как и split/join.

use strict; 
use warnings; 
use Benchmark qw(cmpthese); 

my $string = "ABCDEF" x 1000; 

cmpthese(-1, { 
    keep  => 'my $s = $string; $s =~ s/.\K(?=.)/,/g', 
    lookaround => 'my $s = $string; $s =~ s/(?<=.)(?=.)/,/g', 
    splitjoin => 'my $s = $string; $s = join ",", split(//, $string)' 
}); 

Выход:

    Rate splitjoin lookaround  keep 
splitjoin 6546367/s   --  -6%  -47% 
lookaround 6985568/s   7%   --  -44% 
keep  12392841/s  89%  77%   -- 
+0

Кажется, всегда подавайте в то же время ... Хороший ответ. – Lucas

+0

@ Lucas Спасибо. Да, конкуренция иногда бывает жестокой. – TLP

+0

'unpack '(a) *'' быстрее, чем 'split //', но недостаточно, чтобы догнать «keep». – ikegami

1
my $str = "ABCDEFGHIJKL"; 

my @chars = $str =~ /./sg; 

print join ",", @chars; 
2
$ perl -le 'print join(",", unpack("(A)*", "hello"))' 
h,e,l,l,o 

$ perl -le 'print join(",", unpack("C*", "hello"))' 
104,101,108,108,111 

$ perl -le 'print join(",", unpack("(H2)*", "hello"))' 
68,65,6c,6c,6f 
+0

Мне нравятся эти. Я думал в 'unpack' функции, но не привык к ней. И кажется довольно быстро. ** + 1 ** – Birei

+0

@Birei, версия '(A) *' меньше, чем на половину, так же, как и мой запуск 'cmpthese'. Мне все еще интересно, действительно ли broncofan7 хочет буквы, поскольку он говорит «байты». –

1

Если вы пытаетесь напечатать строки с меньшими накладными расходами, вы можете просто напечатать строку в то время как вы разобрать его, а чем полное преобразование в памяти, то есть

while (m/(.)\B/gc){ 
print "$1,"; 
}; 
if (m/\G(.)/) { 
    print "$1\n"; 
} 
+0

'\ B' умный, но только если знаки препинания и другие символы границы слова не отображаются в строке. – TLP

+0

Да, если строки не так просты, как в вопросе, им может потребоваться отложить печать каждой буквы до тех пор, пока не появится следующая буква, чтобы они могли нарезать, выключить последнюю и распечатать ее. Тем не менее подход m/(.)/g все же должен быть адаптирован. –

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