Удаление дубликатов строк из файла

Тема в разделе "WASM.ZEN", создана пользователем Asterix, 26 дек 2004.

  1. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    Для меня оказалось проще всего реализовать это на perl,

    но хотелось бы сравнить с реализациями на PHP и Python,

    кто хочет реализовать на C/C++ или asm - дерзайте, тоже

    будет интересно сравнить.
    Код (Text):
    1. #!/usr/bin/perl -w
    2.  
    3. open(IN, "< in.txt") or die "Can't open file: $!";
    4. open(OUT, "+> out.txt") or die "Can't open file out.txt for writing: $!";
    5.  
    6. @input = <IN>;
    7. close(IN);
    8. %seen = ();
    9.  
    10. foreach $item (@input)
    11. {
    12.   unless ($seen{$item})
    13.   {
    14.     $seen{$item} = 1;
    15.     print OUT $item;
    16.   }
    17. }
    18. close(OUT);
     
  2. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    То же самое на Python'е:
    Код (Text):
    1. #! /usr/bin/env python
    2.  
    3. input = open('in.txt', 'r')
    4. output = open('out.txt', 'w')
    5. linesarray = input.readlines()
    6. input.close()
    7. seen = []
    8. for i in range(len(linesarray)):
    9.     if seen.count(linesarray[i]) == 0:
    10.         seen.append(linesarray[i])
    11.         output.write(linesarray[i])
    12.  
    13. output.close()
     
  3. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    А что на PHP никто не программирует или боимся проиграть perl'у?



    Может тогда кто на java напишет..?
     
  4. vinnie_pooh

    vinnie_pooh New Member

    Публикаций:
    0
    Регистрация:
    30 июн 2004
    Сообщения:
    98
    Код (Text):
    1. $strings = File("In.txt");
    2. $file_out = fopen("Out.txt", "w");
    3. $strings = array_unique($strings);
    4. foreach($strings as $value)
    5.     fputs($file_out, $value);
    6. fclose($file_out);
    А если находить дубликаты вручную, то мне больше нравится традиционный for, чем foreach:
    Код (Text):
    1. $strings = File("In.txt");
    2. $file_out = fopen("Out.txt", "w");
    3. $length = sizeof($strings);
    4. for($i = 0; $i < $length; $i++)
    5. {
    6.     for($j = $i + 1; $j < $length; $j++)
    7.         if($strings[$i] == $strings[$j])
    8.             break;
    9.     if($j == $length)
    10.         fputs($file_out, $strings[$i]);
    11. }
    12. fclose($file_out);
     
  5. volodya

    volodya wasm.ru

    Публикаций:
    0
    Регистрация:
    22 апр 2003
    Сообщения:
    1.169
    Ха-ха-ха... Неэффективно. Можно быстрее :)
     
  6. vinnie_pooh

    vinnie_pooh New Member

    Публикаций:
    0
    Регистрация:
    30 июн 2004
    Сообщения:
    98
    volodya



    Ты о втором варианте или об обоих? Как эффективнее?
     
  7. volodya

    volodya wasm.ru

    Публикаций:
    0
    Регистрация:
    22 апр 2003
    Сообщения:
    1.169
    Вот это -


    Код (Text):
    1.  
    2. foreach $item (@input)
    3. {
    4.   unless ($seen{$item})
    5.   {
    6.     $seen{$item} = 1;
    7.     print OUT $item;
    8.   }
    9. }
    10.  




    в принципе, ничего. Но логика немножко извратная.

    Ну, а сие:


    Код (Text):
    1.  
    2. for($i = 0; $i < $length; $i++)
    3. {
    4.     for($j = $i + 1; $j < $length; $j++)
    5.         if($strings[$i] == $strings[$j])
    6.             break;
    7.     if($j == $length)
    8.         fputs($file_out, $strings[$i]);
    9. }
    10.  




    цикл в цикле - О(N<sup>2</sup>) - чересчур.



    Истинное же решение было предложено Sten'ом давно на этом же форуме.

    Если предельно кратко. В виде псевдокода.



    1. Прочитать файл в массив @arr

    2. Отобразить @arr на %arr при помощи map.



    Все. На шаге 2 будут удалены все дубликаты. Причем, очень эффективным способом.
     
  8. vinnie_pooh

    vinnie_pooh New Member

    Публикаций:
    0
    Регистрация:
    30 июн 2004
    Сообщения:
    98
    Скорее всего, я неправ, но цикл в цикле - меньшее зло, чем вызов процедуры в цикле. А у меня внутренний цикл запускается каждый раз с меньшим количеством итераций. А вообще - все это неважно, жизнь прекрасна, а сетевое программирование - медленно.
     
  9. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    volodya

    > в принципе, ничего. Но логика немножко извратная.



    Логика самая что ни на есть прямая, если элемента с именем

    $item нет в хэше, то можно print его в файл, плюс добавить элемент в хэш :)



    > Неэффективно. Можно быстрее :)



    Ну не знаю, как его сравнивать по эффективности, это ж не асм чтоб засунуть код в профайлер..
     
  10. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    > Все. На шаге 2 будут удалены все дубликаты.



    Тогда нужен будет ещё шаг 3, чтоб распечатать в файл :derisive:
     
  11. volodya

    volodya wasm.ru

    Публикаций:
    0
    Регистрация:
    22 апр 2003
    Сообщения:
    1.169
    Да хоть четыре. Все будет быстрее, чем хранить твои ... э-э-э ... алгоритмы :)
     
  12. volodya

    volodya wasm.ru

    Публикаций:
    0
    Регистрация:
    22 апр 2003
    Сообщения:
    1.169
  13. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    volodya

    > http://www.unix.org.ua/orelly/perl/perlnut/ch06_05.htm



    О! Эта книга у меня есть.

    С этим понятно но не совсем, т.е. листинг я получить не смог.



    > 1. Прочитать файл в массив @arr

    2. Отобразить @arr на %arr при помощи map.




    Хотел бы увидеть реализацию..

    Что-то типа:
    Код (Text):
    1. %hash = map { genkey($_), $_ } @array;


    ???
     
  14. volodya

    volodya wasm.ru

    Публикаций:
    0
    Регистрация:
    22 апр 2003
    Сообщения:
    1.169
  15. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    volodya



    Понял! :)
    Код (Text):
    1. #!/usr/bin/perl -w
    2.  
    3. open(IN, "< in.txt") or die "Can't open file: $!";
    4. open(OUT, "+> out.txt") or die "Can't open file out.txt for writing: $!";
    5.  
    6. @lines = <IN>;
    7. close(IN);
    8.  
    9. %hash = map {$_, 0} @lines;
    10. @lines = sort keys %hash;
    11.  
    12. print OUT @lines;
    13.  
    14. close(OUT);




    А куда девался bsl_zcs ?
     
  16. volodya

    volodya wasm.ru

    Публикаций:
    0
    Регистрация:
    22 апр 2003
    Сообщения:
    1.169
    Может, ему просто наскучил форум...

    Увы, здесь мало алгоритмистов высокого класса :dntknw: Все больше про иконочки в трее спрашивают...
     
  17. Same

    Same New Member

    Публикаций:
    0
    Регистрация:
    23 окт 2003
    Сообщения:
    114
    На PHP можно сделать короче и без циклов например(модифицируя пример товарища выше)
    Код (Text):
    1.  
    2. $strings = array_unique(File("In.txt"));
    3. $file_out = fopen("Out.txt", "w");
    4. fwrite ($file_out,implode("",$strings));
    5. fclose($file_out);
    6.  


    Или даже так
    Код (Text):
    1.  
    2. $file_out = fopen("Out.txt", "w");
    3. fwrite ($file_out,implode("",array_unique(File("In.txt"))));
    4. fclose($file_out);
    5.