【问题标题】:Case insensitive search for multiple matches in a hash, merge the keys and add up the values不区分大小写搜索哈希中的多个匹配项,合并键并将值相加
【发布时间】:2017-08-23 03:47:47
【问题描述】:

我有一个包含非常大的单词(键)列表及其频率(值)的哈希。
我的问题是同一个词可能会在不同的情况下出现多次,如下所示:

de => 14477841
la => 6577441
et => 5327316
PAR => 1670264
PaR => 1669878
PAr => 1669877    

当发生这种情况时,我想在哈希中找到同一个单词的所有不同版本,无论大小写如何,并在将值相加时合并它们,所以在这里我会得到:

de => 14477841
la => 6577441
et => 5327316
par => 5010019

(“par”在这里是小写的,但我不在乎,只要它只有一个版本。)

我尝试获取数组中的不同键,并检查该列表中每个项目的不同版本是否存在于哈希中。有很多不同的案例模式是我想不到也很难预测的。

这是我的代码示例,值得一提(它部分有效,但我仍然得到重复)

my %hashoutput;
my %hash = map { my ( $key, $value ) = split "\t"; ( $key, $value ) } @lignes;

foreach $ligne (@lignes) #list of keys and values separated by a tab
{

($cleorigine, $valeur) = split /\t/, $ligne;    #get the key and value
$cle = $cleorigine =~ s/^([A-Z])/lc($1)/gr;     # different versions of it
$clemaj = $cleorigine =~ s/^([a-z])/uc($1)/ge;

    if ($cleorigine !~ /[0-9]{2}/g)
    {
        if ($ligne =~ /^([A-Z]|[ÉÈÊÂÀÙÛÇÔÎÏ])/g)
        {
            if (exists $hash{lc($cleorigine)})
            {
                $valeur1 = $valeur + $hash{lc($cleorigine)};    
                $hashoutput{ $cleorigine } = $valeur1;
            }
            if (not exists $hash{lc($cleorigine)})
            {
                if (exists $hash{$cle})
                {
                    $valeur2 = $valeur + $hash{$cle};
                    $hashoutput{ $cleorigine } = $valeur2;
                }
            }
        }
        elsif ($ligne =~ /^([a-z]|[éèêâàùûçôîï])/g)
        {

            if (exists $hash{$clemaj})
            {
            }
            elsif (not exists $hash{uc($clemaj)}) 
            {
                {
                    $hashoutput{ $cleorigine } = $valeur;
                }
            }

        }
    }
}

有更好/更简单的方法吗?

【问题讨论】:

  • 最简单的方法是使用lc 构建一个全新的哈希来规范化键(假设为ascii)
  • 难道不是只保留其中一个值而不是将它们相加吗?
  • 您必须为%old_hash中的所有键添加值:$new_hash{lc $key} += $old_hash{$key};

标签: perl hash


【解决方案1】:

通过聚合等效键的值从旧哈希创建新哈希

像这样。请注意,数据会从原始哈希中删除,以节省空间。 fc 运算符执行 Unicode 大小写折叠,以便它可以处理非 ASCII 字符

use strict;
use warnings 'all';
use feature 'fc';

my %data = (
    de  => 14477841,
    la  =>  6577441,
    et  =>  5327316,
    PAR =>  1670264,
    PaR =>  1669878,
    PAr =>  1669877,
);

my %new_data;

$new_data{ fc $_ } += delete $data{$_} for keys %data;

use Data::Dump 'dd';
dd \%new_data;

输出

{ de => 14477841, et => 5327316, la => 6577441, par => 5010019 }

【讨论】:

  • 我不知道 fc 功能,一如既往的正确!
猜你喜欢
  • 1970-01-01
  • 2021-04-22
  • 2016-09-04
  • 1970-01-01
  • 2018-04-12
  • 1970-01-01
  • 1970-01-01
  • 2016-06-27
  • 2013-05-04
相关资源
最近更新 更多