Nano Hash - криптовалюты, майнинг, программирование

Быстрая альтернатива grep -f

файл.содержит.запрос.txt

ENST001

ENST002

ENST003

файл.для.поиска.в.txt

ENST001  90

ENST002  80

ENST004  50

Поскольку у ENST003 нет записи во втором файле, а у ENST004 нет записи в первом файле, ожидаемый результат будет следующим:

ENST001 90

ENST002 80

Чтобы выполнить множественный запрос в конкретном файле, мы обычно делаем следующее:

grep -f file.contain.query <file.to.search.in >output.file

так как у меня около 10000 запросов и почти 100000 необработанных файлов в file.to.search.in, это занимает очень много времени (около 5 часов). Есть ли быстрая альтернатива grep -f ?

15.07.2012

  • Каковы ваши потребности? Вам нужен файл со строками второго, отфильтрованными с ключами первого? 15.07.2012
  • Я отредактировал ожидаемые результаты 15.07.2012
  • Перенаправление ввода не нужно. 15.07.2012
  • Какая локаль? Попробуйте LANG=C grep -F ... и посмотрите, улучшится ли скорость благодаря локали и (как предусмотрительно советует @tripleee) фиксированному сопоставлению строк. 16.07.2012
  • См. также мой ответ awk, предоставленный похожий вопрос. 13.01.2018

Ответы:


1

Если вам нужен вариант с чистым Perl, считайте ключи файла запроса в хэш-таблицу, а затем проверьте стандартный ввод по этим ключам:

#!/usr/bin/env perl
use strict;
use warnings;

# build hash table of keys
my $keyring;
open KEYS, "< file.contain.query.txt";
while (<KEYS>) {
    chomp $_;
    $keyring->{$_} = 1;
}
close KEYS;

# look up key from each line of standard input
while (<STDIN>) {
    chomp $_;
    my ($key, $value) = split("\t", $_); # assuming search file is tab-delimited; replace delimiter as needed
    if (defined $keyring->{$key}) { print "$_\n"; }
}

Вы бы использовали его так:

lookup.pl < file.to.search.txt

Хеш-таблица может занимать довольно много памяти, но поиск выполняется намного быстрее (поиск в хэш-таблице осуществляется за постоянное время), что удобно, поскольку у вас в 10 раз больше ключей для поиска, чем для хранения.

15.07.2012
  • Это Феррари по сравнению с grep -f .. Спасибо 15.07.2012

  • 2

    Если у вас фиксированные строки, используйте grep -F -f. Это значительно быстрее, чем поиск по регулярным выражениям.

    15.07.2012

    3

    Этот код Perl может помочь вам:

    use strict;
    open my $file1, "<", "file.contain.query.txt" or die $!;
    open my $file2, "<", "file.to.search.in.txt" or die $!;
    
    my %KEYS = ();
    # Hash %KEYS marks the filtered keys by "file.contain.query.txt" file
    
    while(my $line=<$file1>) {
        chomp $line;
        $KEYS{$line} = 1;
    }
    
    while(my $line=<$file2>) {
        if( $line =~ /(\w+)\s+(\d+)/ ) {
            print "$1 $2\n" if $KEYS{$1};
        }
    }
    
    close $file1;
    close $file2;
    
    15.07.2012
  • Вы забыли проверить возвращаемое значение системных вызовов. 15.07.2012

  • 4

    Если файлы уже отсортированы:

    join file1 file2
    

    если не:

    join <(sort file1) <(sort file2)
    
    15.07.2012

    5

    Если вы используете Perl версии 5.10 или новее, вы можете объединить термины «запроса» в регулярное выражение, разделив термины запроса «вертикальной чертой». (Например: ENST001|ENST002|ENST003) Perl строит «дерево», которое, подобно хэшу, выполняет поиск за постоянное время. Он должен работать так же быстро, как и решение с использованием хэша поиска. Просто чтобы показать другой способ сделать это.

    #!/usr/bin/perl
    use strict;
    use warnings;
    use Inline::Files;
    
    my $query = join "|", map {chomp; $_} <QUERY>;
    
    while (<RAW>) {
        print if /^(?:$query)\s/;
    }
    
    __QUERY__
    ENST001
    ENST002
    ENST003
    __RAW__
    ENST001  90
    ENST002  80
    ENST004  50
    
    15.07.2012

    6

    MySQL:

    Импорт данных в Mysql или аналогичный обеспечит огромное улучшение. Будет ли это осуществимо? Результат можно было увидеть через несколько секунд.

    mysql -e 'select search.* from search join contains using (keyword)' > outfile.txt 
    
    # but first you need to create the tables like this (only once off)
    
    create table contains (
       keyword   varchar(255)
       , primary key (keyword)
    );
    
    create table search (
       keyword varchar(255)
       ,num bigint
       ,key (keyword)
    );
    
    # and load the data in:
    
    load data infile 'file.contain.query.txt' 
        into table contains fields terminated by "add column separator here";
    load data infile 'file.to.search.in.txt' 
        into table search fields terminated by "add column separator here";
    
    15.07.2012
  • Я не проверял это, но он будет работать с небольшой настройкой в ​​​​зависимости от вашей ситуации. Это займет очень мало памяти, если вы не хотите, чтобы он был основан на оперативной памяти. 15.07.2012

  • 7

    Это может быть немного устаревшим, но оно создано специально для простых утилит UNIX. Дано:

    • ключи фиксированной длины (здесь 7 символов)
    • файлы сортируются (верно в примере), что позволяет использовать быструю сортировку слиянием

    Потом:

    $ sort -m file.contain.query.txt file.to.search.in.txt | tac | uniq -d -w7
    
    ENST002  80
    
    ENST001  90
    

    Варианты:

    Чтобы удалить номер, напечатанный после ключа, удалите команду tac:

    $ sort -m file.contain.query.txt file.to.search.in.txt | uniq -d -w7
    

    Чтобы сохранить порядок сортировки, добавьте в конце дополнительную команду tac:

    $ sort -m file.contain.query.txt file.to.search.in.txt | tac | uniq -d -w7 | tac
    
    14.03.2019
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..