Модераторы: ginnie, korob2001

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Нужно найти дубликаты в двумерном массиве, пожалуйста дайте SUB умоляю 
V
    Опции темы
burakov
Дата 12.8.2009, 16:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 554
Регистрация: 28.7.2006

Репутация: нет
Всего: нет



Добрый день 
есть массив ссылок на массивы... (двухмерный массив) не хеш (индексы числовые).

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

целый день сижу уже - башка дальше первого уровня не варит smile... наверное не тяну еще :(

пожалуйста дайте код - как это сделать...

Спасибо... огромное...

навсякий случай код как я создал двумерный массив

вот есть файл TXT через 3 строки разделенный символом * 
вот то что между звездочками это массив второго уровня,
а массив первого уровня это массив ссылок на массивы второго уровня 

Код

my $file = 'file.txt';
my @array = (); my $array = ();

open (FILE, $file) or die; 
while (my $str = <FILE>) {
    if ($str !~ /^\*/) {
        push (@$array, $str);
    } else {
        push (@array, $array); 
        $array = ();
    }
}
close (FILE); 

foreach my $e1 (@array) {
    foreach my $e2 (@$e1) {
        print $e2;
    } 
}




...
все ж таки пока писал подумал и ....

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




Это сообщение отредактировал(а) burakov - 12.8.2009, 16:34


--------------------
Нотный архив http://libnote.ru скачать ноты бесплатно
PM MAIL   Вверх
ginnie
Дата 12.8.2009, 16:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 6
Всего: 49



burakov, для массивов второго уровня надо придумать хэш-функцию, по которой находить одинаковые массивы. Далее задача легко решается с помощью хэша.


--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
amg
Дата 12.8.2009, 22:34 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: 9
Всего: 50



Например, так:
Код
my %h;
@array = grep {! $h{"@$_"}++} @array;

Если строки в файле очень длинные, то сэкономить немного памяти можно, используя в качестве хэширующей функции не объединение в строку элементов массива второго уровня, а, например, md5-сумму этой строки.
PM MAIL   Вверх
sir_nuf_nuf
Дата 13.8.2009, 00:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 920
Регистрация: 6.1.2008

Репутация: нет
Всего: 31



amg, вам, как любителю написать покороче еще вариант
Код

@arr = values %{{map {$_ => $_} @arr}};

если в массиве не ссылки то можно и 
Код

@arr = keys %{{map {$_ => 1} @arr}};



--------------------
user posted image
user posted image
PM MAIL Jabber   Вверх
burakov
Дата 13.8.2009, 08:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 554
Регистрация: 28.7.2006

Репутация: нет
Всего: нет



Огромное спасибо...
попробовал

Код

my %h;
@array = grep {! $h{"@$_"}++} @array;



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

прокомментируйте пожалуйста код.... так все компактно написано... что начинающему трудно понять


Понял только, что 
grep чего то фильтрует из массива @array
но вот это вот {! $h{"@$_"}++} ???






--------------------
Нотный архив http://libnote.ru скачать ноты бесплатно
PM MAIL   Вверх
sir_nuf_nuf
Дата 13.8.2009, 08:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 920
Регистрация: 6.1.2008

Репутация: нет
Всего: 31



Код

my %h;
@array = grep {! $h{"@$_"}++} @array;

grep для каждого элемента массива выполняет код 
Код

! $h{"@$_"}++

Если результат окажется истинным - то элемент проходит, нет - отбрасывается.
Что делает это код:
"@$_" - это склеивает элемент массива (который является ссылкой на другой массив) в строку
Так если $a = [3,4,5,6,1]; то "@$a" = "34561" - строка.
Далее это строка используется как ключ в хеше %h.
Если она туда уже помещалась (т.е. мы наткнулись на дубль), то $h{"@$_"} - вернет истину, !$h{"@$_"} - вернет ложь
и это элемент будет отброшен как не уникальный.
В случае, если такого ключа в хэше еще нет (т.е. это уникальный элемент) - то ключ добавляется в хеш
с помощью автоинкримента $h{"@$_"}++ 
На самом деле автоинкримент проистходит всегда, просто для элементов которые кладутся в хеш впервые $h{"@$_"}++ - ложь
а для тех что не впревые истина.

В оригинале эта фича выглядела так:
Код

my %h;
@array = grep {! $h{$_}++} @array;

Это amg ее приспособил под начальные условия.

Добавлено через 1 минуту и 14 секунд
Ну кстати .. для вашей задачи можно приспособить и мой вариант:
Код

@arr = values %{{map {"@$_" => $_} @arr}};



--------------------
user posted image
user posted image
PM MAIL Jabber   Вверх
burakov
Дата 13.8.2009, 09:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 554
Регистрация: 28.7.2006

Репутация: нет
Всего: нет



Спасибо, 
sir_nuf_nuf

но Ваш вариант мне еще более непонятен (хотя в принципе не "более" , а "также")
просто я в своих книжках функцию map не нашел...

если не трудно пожалуйста прокомментируйте пожалуйста и свой код
    
Код

@arr = values %{{map {$_ => $_} @arr}};



Спасибо.


я так понял изначально все эти дела применяются для удаления дубликатов из обыкновенного одномерного массива...
чем и занялся чтобы понять как все работает... 
и возникли вопросы 

Код

use strict; 
use warnings;

my @array1 = (1..10); 
my @array2 = (1..10); 
my @array3 = (@array1,@array2); 
print "@array3\n";

my %h;
@array3 = grep ($h{"$_"}++, @array3);
print "@array3\n";



$h{"$_"}++

почему то работает и без восклицательного знака (и с восклицательным знаком тоже работает)...
а вот без ++ не работает хотя вроде бы должно... (судя по приведенному выше разъяснению)

так что хотя все работает smile пока что для меня это как чудо smilesmilesmile !

Это сообщение отредактировал(а) burakov - 13.8.2009, 09:29


--------------------
Нотный архив http://libnote.ru скачать ноты бесплатно
PM MAIL   Вверх
sir_nuf_nuf
Дата 13.8.2009, 10:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 920
Регистрация: 6.1.2008

Репутация: нет
Всего: 31



Цитата(burakov @  13.8.2009,  09:05 Найти цитируемый пост)
просто я в своих книжках функцию map не нашел

выкидывай их. или на розжиг костра.
perldoc map

Попробуй запустить это:
Код

print map {$_ * 2} (1, 2, 3, 5);


Стало понятнее ?

Цитата(burakov @  13.8.2009,  09:05 Найти цитируемый пост)
почему то работает и без восклицательного знака

не работает. Вам показалось. В таком случае вы отбрасывает первый встретившийся элемент, а кладете все ему равные - как результат действительно уникальные элементы в результат не попадают.



--------------------
user posted image
user posted image
PM MAIL Jabber   Вверх
ginnie
Дата 13.8.2009, 15:38 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 6
Всего: 49



burakov, имейте ввиду, что хэш-функцию нужно выбирать исходя из данных очень аккуратно. Например, если использовать в качестве хэш-функции конкатенацию элементов через пробел ("@$_"), то массивы (1,2,3) и ('1 2', 3) будут неверно интерпретированы, как одинаковые.


--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
KSURi
Дата 13.8.2009, 17:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 887
Регистрация: 8.6.2006
Где: Russia

Репутация: 5
Всего: 27



Кстати, простая конкатенация не будет является хэш-функцией массива)
Чтобы избежать ситуации, которую описал ginnie, достаточно воспользоваться встроенной функцией crypt().


--------------------
Died at Life.pl line 21
PM Jabber   Вверх
ginnie
Дата 13.8.2009, 19:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 6
Всего: 49



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


--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
burakov
Дата 14.8.2009, 08:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 554
Регистрация: 28.7.2006

Репутация: нет
Всего: нет



Спасибо...
Кое что я понял, хотя до полного понимания вопроса ее чувствую далеко...

поскольку удаление дубликатов из массива довольно распространенная необходимость...
Прошу опытных товарищей привести пример кода удаления дубликатов из двумерного массива с использованием функции crypt() (чтобы исключить вариант описанный ginnie).

Спасибо.




--------------------
Нотный архив http://libnote.ru скачать ноты бесплатно
PM MAIL   Вверх
KSURi
Дата 14.8.2009, 08:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 887
Регистрация: 8.6.2006
Где: Russia

Репутация: 5
Всего: 27



Вы попробуйте сами сначала написать, а потом вам помогут ошибки поправить


--------------------
Died at Life.pl line 21
PM Jabber   Вверх
shamber
Дата 14.8.2009, 09:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1422
Регистрация: 5.9.2006
Где: Россия

Репутация: 1
Всего: 18



KSURi, да ладно smile так же проще smile
PM MAIL Jabber   Вверх
ginnie
Дата 14.8.2009, 10:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 6
Всего: 49



burakov, я тут немного подумал, и понял, что не совсем корректно описал свое решение в самом начале.
Цитата

для массивов второго уровня надо придумать хэш-функцию, по которой находить одинаковые массивы. Далее задача легко решается с помощью хэша

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

my $plain_array_view = join('', map { crypt($_, 'any text') } @array);

Такой вариант не исключает возможности получения одинакового представления для двух разных массивов, но это крайне маловероятно.


--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl: Системное программирование"
korob2001
sharq
  • В этом разделе обсуждаются вопросы относящиеся только к системному программированию на Perl
  • Если ваш вопрос не относится к системному или CGI программированию, задавайте его в общем разделе
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.0633 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.