source

는 해시의 또 다른 배열(perl)에서 팔지 않는 해시도 하나의 배열에 있는 요소 확인.

factcode 2022. 9. 16. 22:59
반응형

는 해시의 또 다른 배열(perl)에서 팔지 않는 해시도 하나의 배열에 있는 요소 확인.

전 초보자 perl 프로그래머 어떤 요소들 해시의 배열지만 다른에서 확인하려고 노력하고 있습니다.나는" 새로운"배열을 검색하는 경우는 이드, 제목을 식별하는 그리고"오래 된"배열에서 존재하지 않는 요소를 만들어 내고 있습니다.

나는 염기성 for()많이 한세트를 돌보고 있지만 그보다는 효율적으로 그것을 하고 싶어요 믿는다.이것은 오직 grep()사용하는 것과지 못해 돌아왔다.

이 배열 데이터베이스로부터 같은: 지어진다.

use DBI;
use strict;
use Data::Dumper;
use Array::Utils qw(:all);
sub db_connect_new();
sub db_disconnect_new($);
sub db_connect_old();
sub db_disconnect_old($);

my $dbh_old   = db_connect_old();
my $dbh_new   = db_connect_new();

# get complete list of articles on each host first (Joomla! system)
my $sql_old   = "select id,title,created from mos_content;"; 
my $sql_new   = "select id,title,created from xugc_content;";

my $sth_old   = $dbh_old->prepare($sql_old);
my $sth_new   = $dbh_new->prepare($sql_new);

$sth_old->execute();
$sth_new->execute();

my $ref_old;
my $ref_new;

while ($ref_old = $sth_old->fetchrow_hashref()) {
  push @rv_old, $ref_old;
}

while ($ref_new = $sth_new->fetchrow_hashref()) {
  push @rv_new, $ref_new;
}

my @seen = ();
my @notseen = ();
foreach my $i (@rv_old) {
   my $id = $i->{id};
   my $title = $i->{title};
   my $created = $i->{created};
   my $seen = 0;
   foreach my $j (@rv_new) {
      if ($i->{id} == $j->{id}) {
         push @seen, $i;
         $seen = 1;
      }
   }
   if ($seen == 0) {
       print "$i->{id},$i->{title},$i->{state},$i->{catid},$i->{created}\n";
      push @notseen, $i;
   }
}

때 Dumper(@ rv_old)이들을 출력할를 사용하여 그 배열 다음과 같이 보인다.

$VAR1 = {
          'title' => 'Legal Notice',
          'created' => '2004-10-07 00:17:45',
          'id' => 14
        };
$VAR2 = {
          'created' => '2004-11-15 16:04:06',
          'id' => 86096,
          'title' => 'IRC'
        };
$VAR3 = {
          'id' => 16,
          'created' => '2004-10-07 16:15:29',
          'title' => 'About'
        };

나는 배열 추천서를 써grep()를 사용하는 나는 배열, 해시도, 그리고 추천서 잘 충분히 그렇게 할 적절한 이해할 거라 생각하지 않아 노력했다.내 실패했다 grep()시도 아래에 있다.나는 이것을 어떻게 적절히 처리에 의견을 주시면 고맙겠습니다.

이것 문제는 어떻게 해시의 두번째 배열의 아이디 필드 참조하기 위해 알지 않다고 믿는다.나는 본 적이 있는 예 grep()을 사용하여 대부분의 마찬가지 그저 전체 배열을 따라, 규칙적인 grep(1)으로 있다.나는 한 배열을 반복하는 데,는 이드 분야에서 다른 배열에서는 이드 분야와 각 값에 확인이 필요하다.

  my $rv_old_ref        = \@rv_old;
  my $rv_new_ref        = \@rv_new;

  for my $i ( 0 .. $#rv_old) {
    my $match = grep { $rv_new_ref->$_ == $rv_old_ref->$_ } @rv_new;
    push @notseen, $match if !$match;
  }

나도:grep() 위에 변화 시도했다.

1) if (($p) = grep ($hash_ref->{id}, @rv_old)) {
2) if ($hash_ref->{id} ~~ @rv_old) {

는 배열을 비교하는데 도서관이 있어.하지만, 당신의 비교(배열 요소로서 hashrefs다)고 이 적어도 제가 알고 있어 모든 모듈의 사용 복잡하게 만드는 복잡한 데이터 구조물을 포함한다.

그래서 여기 손으로 하는 방법이 있습니다.표시된 어레이와 해당 복사본을 하나의 값이 변경된 상태로 사용합니다.

use warnings;
use strict;
use feature 'say';

use List::Util qw(none);   # in List::MoreUtils with older Perls
use Data::Dump qw(dd pp);

sub hr_eq {
    my ($e1, $e2) = @_; 
    return 0 if scalar keys %$e1 != scalar keys %$e2;
    foreach my $k1 (keys %$e1) {
       return 0 if !exists($e2->{$k1}) or $e1->{$k1} ne $e2->{$k1};            
    }   
    return 1
}

my @a1 = ( 
    { 'title' => 'Legal Notice', 'created' => '2004-10-07 00:17:45', 'id' => 14 },
    { 'created' => '2004-11-15 16:04:06', 'id' => 86096, 'title' => 'IRC' },  
    { 'id' => 16, 'created' => '2004-10-07 16:15:29', 'title' => 'About' }
);        
my @a2 = ( 
    { 'title' => 'Legal Notice', 'created' => '2004-10-07 00:17:45', 'id' => 14 },
    { 'created' => '2004-11-15 16:xxx:06', 'id' => 86096, 'title' => 'IRC' },  
    { 'id' => 16, 'created' => '2004-10-07 16:15:29', 'title' => 'About' }
);

my @only_in_two = grep { 
    my $e2 = $_; 
    none { hr_eq($e2, $_) } @a1;
} @a2;

dd \@only_in_two;

하면 에 되어 있는 가 올바르게 식별됩니다.@a2에 that that 에 없는 것@a1 함께)xxx(미국의)

메모들

  • 이렇게 하면 어레이 간의 완전한 차이가 아니라 한 어레이의 요소가 다른 어레이에 없는 요소를 찾을 수 있습니다.그것은 그 질문이 구체적으로 요구하는 것이다.

  • 내용에 포괄적인 hashref)에 하고 되지 않습니다좀 더 포괄적인 라이브러리를 입수하고 싶은 경우를 제외하고, 이 비교는 피할 수 없습니다.Test::More를 참조해 주세요.

  • 은 문자열 즉 문자열 입니다.ne이치노실제 데이터가 특정 요소에 대해 더 적절한 비교를 사용하는 것이 적절한지 확인하십시오.

  • 리스트의 각 요소를 리스트 전체에서 검색하는 것은 O(N*M) 알고리즘입니다.이러한 복잡성의 솔루션은 데이터가 너무 크지 않은 한 사용할 수 있지만, 데이터가 충분히 커지면 크기가 증가하여 분명한 영향을 미치면 빠르게 분해됩니다(사용할 수 없을 정도로 느려집니다).당신의 경우에 대한 감을 잡을 시간을 가져보세요.

    여기에서는 해시를 이용하는 O(N+M) 어프로치가 존재합니다(ikegami answer에 나타나 있습니다.데이터를 표시할 수 있을 만큼 큰 데이터가 있으면 알고리즘적으로 이 방법이 훨씬 더 좋습니다.다만, 어레이는 복잡한 데이터 구조(해쉬렙)를 탑재하고 있기 때문에, 특히 데이터를 알 수 없기 때문에, 동작 프로그램을 작성하려면 , 약간의 작업이 필요합니다.그러나 데이터 용량이 큰 경우에는 반드시 이 기능을 구현해야 합니다.


필터링에 관한 코멘트.

이 질문은 어레이의 각 요소에 대해 올바르게 관찰합니다.이 문제는 어레이가 처리될 때grep, 다른 어레이 전체를 체크할 필요가 있습니다.

이것은, 의 본문에서 행해집니다.grep사용.none목록에서:: Util. 블록 내의 코드가 목록의 모든 요소에 대해 false로 평가되면 true를 반환합니다.따라서 요소 중 "none"이 해당 코드를 충족하면 true를 반환합니다.이것이 요건의 핵심입니다.즉, 요소를 다른 어레이에서 찾을 수 없습니다.

기본 변수는 둘 다 사용하므로 주의해야 합니다.grep그리고.none.

grep의 블록$_에일리어스는 리스트의 현재 처리되고 있는 요소의 에일리어스입니다.grep1개씩 통과하고 이름 있는 변수에 저장합니다($e2) 。none그 블록이 다가오고, 그 블록이 그 '소유'를 한다.$_요소 할당@a1더 많은 정보를 얻을 수 있습니다.의 현재 요소@a2에 카피했기 때문에, 이용하실 수도 있습니다.$e2.

에서 수행된 테스트none서브루틴으로 끌어당겨진다는 것을hr_eq특히 해시 레프의 동등성 비교를 위한 것임을 강조합니다.

이 서브에서 세부사항을 조정할 수 있습니다.일단 퉁명스럽게 쓰는 대신ne각 키의 값에 대해 특정 키의 커스텀 비교를 추가할 수 있습니다.==데이터 구조가 변경되었을 경우, 여기서 상세 내용을 조정할 수 있습니다.

사용할 수 있습니다.grep.

for my $new_row (@new_rows) {
   say "$new_row->{id} not in old"
      if !grep { $_->{id} == $new_row->{id} } @old_rows;
}

for my $old_row (@old_rows) {
   say "$old_row->{id} not in new"
      if !grep { $_->{id} == $old_row->{id} } @new_rows;
}

하지만 이는 O(N*M) 솔루션이지만 O(N+M) 솔루션이 훨씬 더 빠릅니다.

my %old_keys;  ++$old_keys{ $_->{id} } for @old_rows;
my %new_keys;  ++$new_keys{ $_->{id} } for @new_rows;

for my $new_row (@new_rows) {
   say "$new_row->{id} not in old"
      if !$old_keys{$new_row->{id}};
}

for my $old_row (@old_rows) {
   say "$old_row->{id} not in new"
      if !$new_keys{$old_row->{id}};
}

두 개의 데이터베이스가 모두 동일한 데이터베이스에 연결되어 있는 경우, 데이터베이스 자체 내에서 훨씬 더 효율적으로 연결할 수 있습니다.

  1. 가 있는 .id,old_count )DEFAULT 0 및 )의 개요new_count )DEFAULT 0를 참조해 주세요.
  2. INSERT OR UPDATE 테이블로, 「」의 , 「」old_count그 과정에서.
  3. INSERT OR UPDATE 「」의 , 「」new_count그 과정에서.
  4. SELECT의 행0★★★★★★에old_count ★★★★★★★★★★★★★★★★★」0★★★★★★에new_count.
select id,title,created from mos_content
     LEFT JOIN xugc_content USING(id)
     WHERE xugc_content.id IS NULL;

하다, 하다, 하다, 하다, .mos_content 에는 xugc_content.

이는 Perl 코드보다 더 짧습니다.

언급URL : https://stackoverflow.com/questions/55071234/identifying-elements-in-one-array-of-hashes-that-are-not-in-another-array-of-has

반응형