我有一个包含大约 10k 号码的数组 SPLNO。现在我想从数组中的 MDN.TXT 文件(包含大约 1.5 条 lac 记录)中搜索订户号码。如果在数组中找到订户号码,它将执行以下操作。我的问题是它需要更多时间,因为对于一个数字,它要搜索 10k 条记录的整个数组。因此,对于 1.5 lac 记录,它会循环 (1.5lac*10K)。请建议有效的方法。
示例 SPLNO.TXT:
918542054921|30|1|2
918542144944|12|1|2
918542155955|12|1|2 918542166966|12
|1|2
918542255955|12|1|2
918542355955|12|1| 2 91
8542455955|12|1|2
918542555955 |12|1|2
918542955955|12|1|2
示例 MDN.TXT:
8542166966
8542355955
8542555955
awk -F"|" 'FNR==1 { ++counter}
counter==1 {SPLNOPULSE[$1]=$4;SPLNOAMT[$1]=$3;SPLNOMAXLEN[$1]=$2;next}
{
for ( mdn in SPLNOMAXLEN)
{
if ( ($1 ~ "^"mdn && length($1) <=SPLNOMAXLEN[mdn]) || ("91"$1 ~ "^"mdn && length("91"$1) <=SPLNOMAXLEN[mdn]) )
{
print found
}
else
print not found
}
} ' SPLNO.TXT MDN.TXT
答案1
这是一种方法,使用perl
.
#!/usr/bin/perl
# read the subscribers
open(A,"<","SPLNO.TXT");
while(<A>) {
chomp;
@a=split(/\|/,$_);
$splnopulse{$a[0]}=$3;
$splnoamt{$a[0]}=$2;
$splnomaxlen{$a[0]}=$1;
}
close A;
# read the mdn, looking for matches
open(B,"<","MDN.TXT");
while(<B>) {
chomp;
@b=split(/\|/,$_);
foreach $mdn (keys %splnomaxlen) {
if($mdn eq $b[0] || "$mdn" eq "91" . $b[0]) {
print "found\n";
} else {
print "not found\n";
}
}
}
close B;
答案2
在整个文件 2 中搜索文件 1 中的每一行的算法的时间性能为m * n
.其中m
是文件 2 行数,n
是文件 1 行数。这变得非常慢而不是很快。
解决方案是首先对每个文件进行排序(即 *log(n) 时间),然后比较两个文件之间的行,如下所示:
- 使 i=1(文件 1 行号)和 j=1(文件 2 行号)。
a=(file 1)[line i]
与之比较b=(file 2)[line j]
。if a<b;
然后增加 i,返回到 2(检查文件 1 的结尾)。if a>b;
然后增加 j,返回到 2(检查文件 2 的末尾)。if a=b;
这是一个匹配,打印它,增加 i。
其执行时间仅为:(n + m
读取所有行的时间)。
那么,整个过程的执行时间为:n*log(n) + m*log(m) + n + m
。
其中 O(n) 为:n * log(n)
for n > m
.
排序很容易,只需sort
对每个文件使用命令:
sort -t '|' -k 1 file01.csv > file01-sorted.csv
然后在 awk 中执行上述过程。
编辑:我突然想到,如果 SPLNO 的所有 10k 个数字都是唯一的(没有重复)。并且MDN.TXT也有独特的记录。然后,连接两个文件并搜索重复值也将为您提供解决方案。这适用于简单的平等。在大多数情况下,正则表达式匹配会打破这个想法。