2017-01-20 25 views
6

Предположим, у меня большой массив, @stuff и $thing, и я хочу знать, $thing находится в @stuff. Каков наилучший способ сделать это в Perl 6? И с «лучшим» я имею в виду: идиоматический, читаемый, исполнительский; Необязательно в этом порядке.Perl 6: каков наилучший способ проверить, есть ли элемент в списке?

Фактически два отдельных случая. Один из них - это то, где вам нужно сделать много проверок для разных $thing, а другой - где вы делаете это только один или несколько раз.

Давайте сначала рассмотрим первый случай. Я думаю, что знаю (или) правильный ответ.

my $set-of-stuff = set @stuff; 
for @whatever -> $thing { 
    do-something-with($thing) if $thing ∈ $set of stuff; 
} 

Вы действительно можете пропустить первую строку и просто сказать ... if $thing ∈ @stuff, но это почти наверняка будет иметь намного худшую производительность, так как набор создается каждый раз.

Но теперь во втором случае у меня есть только один $thing для проверки. Вышеупомянутое решение работает, конечно, но создавая набор, просто чтобы проверить его один раз, кажется, много накладных расходов. Ярлык

do-something-with($thing) if $thing ∈ @stuff; 

делает немного больше смысла здесь, так как мы только называем это один раз. Но все же мы должны создать набор для одного использования.

Немного более традиционным является:

do-something-with($thing) if @stuff.grep($thing); 

Или потенциально быстрее:

do-something-with($thing) if @stuff.first($thing); 

Но это кажется менее идиоматическое, и, конечно, второй один менее читабельным, чем $thing ∈ @stuff.

Я не думаю, что есть разумное решение, верно? Конечно, это не работает:

do-something-with($thing) if $thing ~~ @stuff; 

Любые мысли?

ответ

11

В зависимости от вашего определения «лучший» или «умный».

Если вы говорите о производительности, я уверен, что

@stuff.first($thing) 

является самым быстрым.

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

$thing ~~ any @stuff 

, который имеет потенциал повышения производительности за счет стандартной даты автоматического нарезания резьбы.

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

Не уверен, что есть «лучший» ответ на этот вопрос.

+0

Спасибо, я должен был подумать о «любом».Однако, по моему опыту, соединения в текущих версиях Rakudo очень медленные, поэтому, вероятно, это не очень хороший вариант (пока). – mscha

+0

А что такое «лучший»? Ну, это зависит от ситуации, я думаю. В идеале, лучшая производительность, идиоматичность (sic?) И читаемость, но на практике вам приходится идти на компромисс. Например, вы можете пожертвовать некоторой производительностью для удобочитаемости, но не много. – mscha

+0

Фактически '[email protected] ($ thing)' должен быть таким же быстрым, как '@ stuff.first ($ thing)' (потому что он останавливается после того, как находит что-то, что соответствует) –