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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как сравнить два значения, не обращая внимания на их тип 
:(
    Опции темы
Danissimo
Дата 15.12.2006, 15:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Пусть даны две хеш-таблицы %new и %$old. Мне нужно удалить из %new все те элементы, значения которых равны значениям соответсвующих элементов в %oldю Вот как я это делаю:
Код

delete @new{grep {
    (!defined $new{$_} && !defined $old->{$_}) ||
    ( defined $new{$_} &&  defined $old->{$_}  &&
    ($new{$_} == $old->{$_} || $new{$_} eq $old->{$_}))
} keys %new};

Меня смущает последняя строчка в условии. Ведь если перл не сможет преобразовать чтроку в число, он подставит 0. Получится, что с обоих концов численного сравнения будут стоять 0, => равенство выполняется.

Как разрулить?
PM MAIL   Вверх
nitr
Дата 15.12.2006, 17:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



хм... а можно оставить так
Код

#!perl -w
use strict;

my %new;
my $old;

$new{'1'} = 1;
$new{'2'} = '2';
$new{'3'} = '3';

$old->{'1'} = "1";
$old->{'2'} = '22';
$old->{'3'} = 3;

delete @new{grep {
    (!defined $new{$_} && !defined $old->{$_}) ||
    ( defined $new{$_} &&  defined $old->{$_}  &&
    ($new{$_} eq $old->{$_}))
} keys %new};

print "new:\n";
foreach (keys %new) {
    print "\t$_ => ".$new{$_}."\n";
}
print "\nold:\n";
foreach (keys %$old) {
    print "\t$_ => ".$old->{$_}."\n";
}


смотри внимательно, там значения как цифры, так и текст smile (в  твоём представлении)

Добавлено @ 17:14 
Код

#!perl -w
use strict;

my $str = "1234";
my $num = 1234;

print "Ravni" if $str eq $num;


посмотри на результат этого очень простого кода ;)


--------------------
PM   Вверх
korob2001
Дата 16.12.2006, 16:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

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



Можно ещё так попробовать:
Код

my %new = ( one => 1, two => 2, three => '3', four => 55, five => 10);
my %old = ( one => 22, two => 2, three => '1', four => '55', five => 14);

for (keys %old) {delete $new{$_} if (exists $new{$_} && ($old{$_} eq $new{$_}))}

Если нужно узнать элементы с какимими значениями были удалены, то можно сделать так:
Код

#!/usr/bin/perl -w
my %new = ( one => 1, two => 2, three => '3', four => 55, five => 10);
my %old = ( one => 22, two => 2, three => '1', four => '55', five => 14);
my @deleted = grep{ $_ } map { delete $new{$_} if exists $new{$_} and $old{$_} eq $new{$_} } keys %old;
print qq[Has been deleted elements with values:\n\t @{[join(", ", @deleted)]}\n];



--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
Nab
Дата 16.12.2006, 20:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



korob2001, не прокатит если будет '5' и '5.0' или '05', хотя в реальности эти значения равны....

Описанный тобой вариант, это из той оперы когда мы тут недавно искали разности массивов, здесь тоже можно при уникальности этих значений просто перевернуть хеш. Но этого в условии нет smile


--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
korob2001
Дата 17.12.2006, 17:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

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



Понял  smile
Код

#!/usr/bin/perl -w
my %new = ( one => 1, two => '02', three => '3', four => 55, five => 10, six => 'd', seven => .5);
my %old = ( one => 22, two => 2, three => 3.0, four => '55', five => 14, six => 'd', seven => 0.5);
my @deleted = grep{ $_ } map {
   if (exists $new{$_}) {
       if ($new{$_} =~ /^\d+(?:\.\d+)?$/ && $old{$_} =~ /^\d+(?:\.\d+)?$/) {
           delete $new{$_} if $old{$_} == $new{$_};
       } else {
           delete $new{$_} if $old{$_} eq $new{$_};
       }
   }
} keys %old;
print qq[Has been deleted elements with values:\n\t @{[join(", ", @deleted)]}\n];


Это сообщение отредактировал(а) korob2001 - 17.12.2006, 17:32


--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
Danissimo
Дата 18.12.2006, 14:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Да, проблема в том, что, скажем, имея
Код

%new = ('key' => 'value');
%old = {'key' => 0};
delete @new{grep {
    (!defined $new{$_} && !defined $old->{$_}) ||
    ( defined $new{$_} &&  defined $old->{$_}  &&
    ($new{$_} == $old->{$_} || $new{$_} eq $old->{$_}))
} keys %new};
print join(', ', keys %new) . "\n";

значение с ключом 'key' будет удалено, а не должно, так как 'value' != 0. Вот это и есть опасность.

Поэтому, видимо, как korob и предложил, без РВ не обойтись. Я вот как сделал:
Код

delete @new{grep {
    my $n = $new{$_};
    my $o = $old->{$_};
    (!defined $n && !defined $o) ||
    ( defined $n &&  defined $o && (
        (
            # both are numbers
            $n =~ /^\s*[+-]?(?:\d*\.)?\d+(?:[eE][+-]?\d+)?\s*$/ &&
            $o =~ /^\s*[+-]?(?:\d*\.)?\d+(?:[eE][+-]?\d+)?\s*$/ &&
            $n == $o
        ) || $n eq $o # at least one is not a number
    ))
} keys %new};


Вот на чем я тестировал:
Код

%new = (
    'remove1' => undef,
    'remove2' => '2e-1',
    'remove3' => '1',
    'retain1' => 'value',
    'retain2' => undef
);
$old = {
    'remove1' => undef,
    'remove2' => '.2',
    'remove3' => 1E0,
    'retain1' => 'oldvalue',
    'retain2' => 'v2'
};


Добавлено @ 14:18 
Да, надо заметить, что по условию, кроме неопределенного, других значений false ('', '0', 0) в хеш-таблицах нету.
PM MAIL   Вверх
nitr
Дата 18.12.2006, 19:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Danissimo, не знаю... попытался с твоим и что? вывело всё нормально...
где ошибка? smile)
Код

#!perl -w
use strict;

my %new = (one => 'value', two => '2', three => 3);
my $old = {one => 0, two => 22, three => '3'};

delete @new{grep {
    (!defined $new{$_} && !defined $old->{$_}) ||
    ( defined $new{$_} &&  defined $old->{$_}  &&
    ($new{$_} eq $old->{$_}))
} keys %new};

print "new:\n";
foreach (keys %new) {
    print "\t$_ => ".$new{$_}."\n";
}
print "\nold:\n";
foreach (keys %$old) {
    print "\t$_ => ".$old->{$_}."\n";
}


ты глядел мой код? smile

Добавлено @ 19:26 
это результат smile и на сколько знаю в перл нет типов ;) но есть "принципы"
Цитата

D:\work>1.pl
new:
        one => value
        two => 2

old:
        three => 3
        one => 0
        two => 22



--------------------
PM   Вверх
korob2001
Дата 19.12.2006, 07:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

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



Цитата(Danissimo @  18.12.2006,  11:16 Найти цитируемый пост)
Да, надо заметить, что по условию, кроме неопределенного, других значений false ('', '0', 0) в хеш-таблицах нету.

Не понял. Что значит нету?
Запусти такой код:
Код

#!/usr/bin/perl

my %hash = (
   false1 => '',
   false2 => undef,
   false3 => '0',
   false4 => 0,
   true1  => 1,
   true2  => "true",
   true3  => '0.0',
   false5 => 0.0,
);

print "\$hash{$_} = " . ($hash{$_} ? "true" : "false") . "\n" for (keys %hash);


Это сообщение отредактировал(а) korob2001 - 19.12.2006, 07:44


--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
Danissimo
Дата 19.12.2006, 13:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Цитата(nitr @ 18.12.2006,  19:24)
Danissimo, не знаю... попытался с твоим и что? вывело всё нормально...

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

delete @new{grep {
    (!defined $new{$_} && !defined $old->{$_}) ||
    ( defined $new{$_} &&  defined $old->{$_}  &&
    ($new{$_} eq $old->{$_}))
} keys %new};

с моими данными, и вот результат:
Код

keys={remove2, retain2, retain1}

Не работает, батенька =) И Nab уже об этом говорил, правда, в ответ на пост Korob'а.

Добавлено @ 13:08 
Цитата(korob2001 @ 19.12.2006,  07:44)
Не понял. Что значит нету?

Это было уточнение. Данные в хеш-таблицах таковы, что лжи, кроме как undef, в них не встретится. Таковы данные, с которыми я работаю.
PM MAIL   Вверх
nitr
Дата 19.12.2006, 23:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Код

keys={remove2, retain2, retain1}

Цитата
Не работает, батенька =)


Хорошо, а что же должно быть в %new, если такие данные:
Код

%new = (
    'remove1' => undef,
    'remove2' => '2e-1',
    'remove3' => '1',
    'retain1' => 'value',
    'retain2' => undef
);
$old = {
    'remove1' => undef,
    'remove2' => '.2',
    'remove3' => 1E0,
    'retain1' => 'oldvalue',
    'retain2' => 'v2'
};
?
remove1 равны
remove3 равны smile (выводим print значений этих ключей ;) )

остаются remove2, retain1, retain2
Что не так? smile


--------------------
PM   Вверх
nitr
Дата 20.12.2006, 02:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



'remove2' => '2e-1', и 'remove2' => '.2',
будут равны если убрать кавычки ;) (заметил Nab ;) )


--------------------
PM   Вверх
Danissimo
Дата 21.12.2006, 16:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Хм. Да, работает. А зуб дашь, что это именно то, что мне требуется? У меня вот сомнения есть. Не могу, правда, привести пример, когда твой вариант сфейлится, но почему-то сомневаюсь я в нем. Не нравится мне eq для стравнения чисел.

Да, и еще, ты вот говоришь, если убрать кавычки, то твой вариант будет работать. Согласен. Но!.. я-то забираю данные из БД. => я не управляю кавычками. Если в БД поле строковое, то и вернется строка. Читай, как будто с кавычками.

Вобщем, интересно было узнать, что eq может сравнивать не только строки, но уверенности в том, что твой вариант сработает как надо, к сожалению, нету.
PM MAIL   Вверх
nitr
Дата 21.12.2006, 23:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Danissimo @  21.12.2006,  16:12 Найти цитируемый пост)
Вобщем, интересно было узнать, что eq может сравнивать не только строки

Код

#!perl -w
use strict;

my $str = "1234";
my $num = 1234;

print "Ravni" if $str eq $num; # Вывод если равны :)

Но с твоим вопросам "КАВЫЧКИ" я ответить не могу smile
Из законов написания и других в математике число 0.2 нельзя записать как .2
Это как одна из ошибок smile Ну раз из БД, значит и делай преобразования в БД =) что ты мучиешься? БД правильно преобразует .2 в 0.2 и 2e-1 в 0.2 smile

Или может korob знает. Скажу точно, что Ларри знает smile поищи конференции, и просто переписки... (но это сложность ;) )


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


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

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


 




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


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

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