подскажите алгоритм

Discussion in 'PHP' started by Termin@L, 6 Feb 2007.

  1. Termin@L

    Termin@L Elder - Старейшина

    Joined:
    7 Dec 2006
    Messages:
    183
    Likes Received:
    43
    Reputations:
    53
    Народ подскажите, как считать большой текстовый файл(допустим словарь) и очистить его от повторов или наоборот, например найти элемент повторяющийся наибольшее кол-во раз, какой самый быстрый способ (желательно на php)?
     
  2. Helios

    Helios Elder - Старейшина

    Joined:
    14 Jan 2007
    Messages:
    414
    Likes Received:
    180
    Reputations:
    103
    Убирал совпадения из фалика в 200000 строк таким макаром:

    Code:
    <?php
    
    $data_in = file("numbers.txt");
    
    
    $data2 = file("base_final.txt");
    
    $data_in = array_merge($data_in, $data2);
    
    sort(&$data_in);
    
    
    $t = count($data_in);
    
    $iterator = 0;
    
    $data_out = array();
    
    $data_out[] = $data_in[0];
    
    for($i = 1; $i < $t; $i++)
    {
    	if($data_in[$i] != $data_in[$iterator])
    	{
    		$data_out[] = $data_in[$i];
    		$iterator = $i;
    	}
    }
    
    file_put_contents("base_final.txt", join("", $data_out));
    
    echo "Done! Total " . count($data_out) . " items";
    ?>
    
     
  3. Srg

    Srg Elder - Старейшина

    Joined:
    27 Jan 2006
    Messages:
    108
    Likes Received:
    12
    Reputations:
    0
    А еще бы комментов :)......
     
    2 people like this.
  4. ZaCo

    ZaCo Banned

    Joined:
    20 Jun 2005
    Messages:
    737
    Likes Received:
    336
    Reputations:
    215
    >>Народ подскажите, как считать большой текстовый файл
    2Helios мало того что алгоритм неэффективен так он еще и под заданную задачу не подходит.
     
  5. Helios

    Helios Elder - Старейшина

    Joined:
    14 Jan 2007
    Messages:
    414
    Likes Received:
    180
    Reputations:
    103
    Комменты:
    После считывания файла все его строки сортирую, при этом одинаковые окажутся рядом. На это совпадение и проверяю. При желании можно прикрутить strtoupper/strtolower дабы не обращать внимания на регистр.

    2ZaCo Напиши эффективнее, ты ж чингачкук.
     
  6. ZaCo

    ZaCo Banned

    Joined:
    20 Jun 2005
    Messages:
    737
    Likes Received:
    336
    Reputations:
    215
    2Helios я напишу вот только задачи не вижу.
     
  7. genom--

    genom-- Elder - Старейшина

    Joined:
    9 Jul 2006
    Messages:
    668
    Likes Received:
    416
    Reputations:
    288
    понимаешь твоя ошибка в том что при сортировке тебе полюбому придется заносить все в массив и они будут немеренно жрать оперативы о-- особенно если словарь метров на 300 ---
     
  8. nerezus

    nerezus Banned

    Joined:
    12 Aug 2004
    Messages:
    3,191
    Likes Received:
    727
    Reputations:
    266
    Либо память, либо скорость.
    Т.к. память безгранична за счет раздела подкачки, то... ;)
     
    1 person likes this.
  9. Termin@L

    Termin@L Elder - Старейшина

    Joined:
    7 Dec 2006
    Messages:
    183
    Likes Received:
    43
    Reputations:
    53
    2 ZaCo задача - находить повторяющиеся элементы в текстовом файле и производить с ними различные действия
     
    #9 Termin@L, 7 Feb 2007
    Last edited: 7 Feb 2007
  10. Helios

    Helios Elder - Старейшина

    Joined:
    14 Jan 2007
    Messages:
    414
    Likes Received:
    180
    Reputations:
    103
    Скрипт ентот исполняться будет не сотню раз одновременно, а в один поток, поэтому на ОЗУ жаловаться ИМХО нет смысла. А насчет того, что считывать нужно весь файл сразу - в другом случае прогонять поиск совпадений по циклу и сортировку пришлось бы после каждого считывания => время исполнения увеличилось бы в разы.

    З.Ы.: Кто знает другие варианты - пишите, а то и самому интерессно)
     
  11. k1b0rg

    k1b0rg Тут может быть ваша реклама.

    Joined:
    30 Jul 2005
    Messages:
    1,182
    Likes Received:
    399
    Reputations:
    479
    Helios

    твой код можно заменить одной функцией array_unique которуая удалит все дубликаты из массива.


    Я думаю алгоритм для больших файлов должен быть следующим:
    открытие файла (fopen)
    чтение строки.
    пробежать по файлу в поисках дубликата с места нахождения этой строки.
    Если найдено то занести в массив.
    В итоге будет два массива, один чистый а в другом будут все найденные совпадения.
     
  12. KSURi

    KSURi tnega AOLPS

    Joined:
    6 Jun 2006
    Messages:
    458
    Likes Received:
    219
    Reputations:
    357
    Это по тому что, написал киба (perl, портировать на php не составит труда)
    Code:
    foreach(@tmp) { push(@unqie,$_) if !$seen{$_}; $seen{$_}=1; }
    @tmp - список в который считывается файл
    @unique - список в котором окажутся все уникальные строки
    %seen - хэш, в котором будут повторы (key=>имя_повтора, value=>всегда 1)
    Хотя я не совсем уверен, что это есть оптимальный алгоритм... Хотя хз...

    UPD:
    Code:
    E:\>perl unique.pl
    All: 1008176; Unique: 1000000; Time: 17 secs
    E:\>
    Oбрабатывался файл размером 25 284 608 байт (1008176 строк)
     
    #12 KSURi, 8 Feb 2007
    Last edited: 8 Feb 2007
  13. k1b0rg

    k1b0rg Тут может быть ваша реклама.

    Joined:
    30 Jul 2005
    Messages:
    1,182
    Likes Received:
    399
    Reputations:
    479
    Написал аналог php'шной функции


    sub array_unique(@)
    {
    @input=@_;
    %temp=();
    foreach $item (@input) {
    push(@output, $item) unless $temp{$item}++;
    }
    return @output;
    }

    использовать так:

    @arr=array_unique(@arr);
     
    1 person likes this.
  14. KSURi

    KSURi tnega AOLPS

    Joined:
    6 Jun 2006
    Messages:
    458
    Likes Received:
    219
    Reputations:
    357
    Я модифицировал функцию от кибы и получилось вот что:
    Code:
    sub array_unique
    {
      my $input=shift;
      my %seen;
      my $i=0;
      foreach(@{$input})
      {
        delete @{$input}[$i] if $seen{$_};
        $seen{$_}=1;
        $i++;
      }
    }
    
    Работает теперь вот так:
    Code:
    E:\>perl unique.pl
    All: 1008176; Unique: 1000000; Time: 8
    E:\>
    
    Вызывать ее теперь вот так: array_unique(\@arr);
     
    #14 KSURi, 8 Feb 2007
    Last edited: 8 Feb 2007
    1 person likes this.