Chinaunix
标题:
[算法] 数据的合并问题
[打印本页]
作者:
patagonia2
时间:
2014-10-11 16:21
标题:
[算法] 数据的合并问题
遇到这个问题,没什么思路。erlang 版的大圣都不会。
http://bbs.chinaunix.net/thread-4156239-1-1.html
求助 !! perl 版的大圣。
文件A: 大约 60000 行
Astrakhan 197
Atkarsk 516
Aznakayevo 99
Azov 146
Babayevo 255
Babushkin 202
Bagrationovsk 477
Bakal 451
Baksan 333
Balabanovo 390
Balakhna 459
Balakovo 401
Balashikha 542
Balashov 542
...
文件B: 大约 8000 行
Q12 207
D23 149
Y11 94
U10 542
Q45 276
A11 482
R08 240
ZAA 250
....
选择数字最接近的
比如
Q12: 207 --> Babushkin: 202
如果最接近的数字有多个 列出所有
比如
U10: 542 --> Balashikha: 542, Balashov: 542
那么输出来的时候,得到结果应该是这样的:
Q12 Babushkin
D23 Azov
Y11 Aznakayevo
U10 Balashov Balashikha
.
.
.
请问各位大圣这种情况怎么处理呢。
作者:
523066680
时间:
2014-10-11 16:43
本帖最后由 523066680 于 2014-10-11 16:47 编辑
有没有更多的数据文本,发一部分到论坛附件,大家方便测试。
还有就是接近的数字,有没有一个限制的阀值。
作者:
huang6894
时间:
2014-10-11 16:56
50更接近49还是51?
作者:
patagonia2
时间:
2014-10-11 17:07
回复
2#
523066680
谢谢指导。
最接近的数字,没有阀值。 就是最接近的。
最接近的数字 = abs(A - B)
文件B
ABC 250
文件A
如果没有 250
但是有最接近的数字,251, 249.....
最接近的数字 = abs(A - B)
Astra 251
...
Cakev 249
..
Demak 249
输出
ABC Astra Cakev Demak
谢谢指导。
作者:
patagonia2
时间:
2014-10-11 17:10
回复
3#
huang6894
谢谢指导。
最接近的数字 = abs(A - B)
abs(50-49) == abs(50-51)
都是最接近的。
谢谢指导。
作者:
523066680
时间:
2014-10-11 19:06
本帖最后由 523066680 于 2014-10-22 21:31 编辑
.............
作者:
523066680
时间:
2014-10-12 13:44
本帖最后由 523066680 于 2014-10-22 21:31 编辑
<代码已删除>
作者:
patagonia2
时间:
2015-11-30 15:49
谢谢指导。
大神们有什么好的代码?
作者:
sunzhiguolu
时间:
2015-11-30 15:57
回复
8#
patagonia2
遇到这个问题,没什么思路。
erlang 版的大圣都不会????
作者:
stanley_tam
时间:
2015-12-01 21:12
2014年的帖。。居然还有人挖出来了。发帖人还回了。。666
文件A和文件B的第一列数据是惟一没有重复的吗?
作者:
MMMIX
时间:
2015-12-01 21:57
回复
8#
patagonia2
你这数据量也不大,直接循环就行了。
作者:
sunzhiguolu
时间:
2015-12-02 00:01
回复
1#
patagonia2
将你的文件 A,B 各贴出 100 行.
另外, A,B 文件的第二列数值表示什么含义? 峰值, 谷值各是是多少?
作者:
stanley_tam
时间:
2015-12-02 21:39
来一发
#!perl
use strict;
use warnings;
use diagnostics;
use List::Util qw{max min};
sub main;
sub load_a_data;
sub find_the_nearest;
main;
sub main {
my $a_data_href = load_a_data();
my $max = max keys %{$a_data_href};
my $min = min keys %{$a_data_href};
# read file B
my $file = 'B.txt';
open my $fh, '<', $file or die "Unable to open file $file:$!$/";
while (defined (my $line = readline $fh) ) {
# body...
chomp $line;
$line =~ s{^\s+ | \s+$}{}gmix;
next if not $line;
my ($word, $num) = split /\s+/, $line;
my $words_aref = find_the_nearest($num, $a_data_href, $max, $min);
print "$word\t@{$words_aref}$/";
}
close $fh;
}
sub load_a_data {
# body...
my %data = ();
my $file = 'A.txt';
open my $fh, '<', $file or die "Unable to open file $file:$!$/";
while (defined (my $line = readline $fh) ) {
# body...
chomp $line;
$line =~ s{^\s+ | \s+$}{}gmix;
next if not $line;
my ($word, $num) = split /\s+/, $line;
push @{ $data{$num} }, $word;
}
close $fh;
return \%data;
}
sub find_the_nearest {
# body...
my ($num, $a_data_href, $max, $min) = @_;
my $words_aref = [];
if (exists $a_data_href->{$num}) {
# if exactly matched
$words_aref = $a_data_href->{$num};
}
else {
if ($num < $min) {
# only need to look for numbers greater than $num
my $new_num = $num;
while (1) {
$new_num += 1;
if (exists $a_data_href->{$new_num}) {
$words_aref = $a_data_href->{$new_num};
last;
}
}
}
elsif ($num > $max){
# only need to look for numbers smaller than $num
my $new_num = $num;
while (1) {
$new_num -= 1;
if (exists $a_data_href->{$new_num}) {
$words_aref = $a_data_href->{$new_num};
last;
}
}
}
else {
# look for numbers both way
my $new_num_bigger = $num;
my $new_num_smaller = $num;
while (1) {
$new_num_bigger += 1;
$new_num_smaller -= 1;
my @words = ();
if (exists $a_data_href->{$new_num_bigger}) {
push @words, @{ $a_data_href->{$new_num_bigger} };
}
if (exists $a_data_href->{$new_num_smaller}) {
push @words, @{ $a_data_href->{$new_num_smaller} };
}
if (scalar @words) {
$words_aref = \@words;
last;
}
}
}
}
return $words_aref;
}
__END__
复制代码
作者:
patagonia2
时间:
2015-12-03 09:19
回复
13#
stanley_tam
谢谢大圣指导。
偶测试看看
作者:
patagonia2
时间:
2015-12-03 09:22
回复
12#
sunzhiguolu
谢谢指导。
第二列数值 > 0
作者:
patagonia2
时间:
2015-12-03 09:27
回复
11#
MMMIX
谢谢指导。
作者:
patagonia2
时间:
2015-12-03 09:30
回复
7#
523066680
大圣为什么删除代码
作者:
substr函数
时间:
2015-12-03 11:36
回复
13#
stanley_tam
while (1) {
$new_num_bigger += 1;
$new_num_smaller -= 1;
方法简单而思路巧妙
确实非常巧妙,赞一个 [
]
作者:
stanley_tam
时间:
2015-12-03 13:10
多谢大神的赞
回复
18#
substr函数
作者:
patagonia2
时间:
2015-12-04 10:20
回复
19#
stanley_tam
呵呵,就是这个意思。
非常感谢大圣,程序没有问题。
作者:
sunzhiguolu
时间:
2015-12-04 18:50
本帖最后由 sunzhiguolu 于 2015-12-04 19:32 编辑
回复
20#
patagonia2
试下: (测试环境: Windows 7)
tr -s [:blank:] < a.txt | sort -t" " -k2n -o a.txt
复制代码
代码如下:
#!/usr/bin/perl
use strict;
use warnings;
use Tie::File;
my ($sFileA, $sFileB, @aData) = ('File A Path', 'File B Path');
tie (my @aFileA, 'Tie::File', $sFileA, mode => 'O_RDONLY');
open (my $fhFileB, '<', $sFileB);
while (<$fhFileB>){
my ($sB1, $sB2) = split;
foreach my $sLine (@aFileA){
my ($sA1, $sA2) = split /\s+/, $sLine;
unless (@aData){
@aData = ($sB1, $sA1, $sA2);
}else{
if (abs ($sA2 - $sB2) <= abs ($aData[-1] - $sB2)){
if ($aData[-1] == $sA2){
@aData = ($aData[0], $aData[1] . ' ' . $sA1, $aData[-1]);
next;
}
$aData[1] = $sA1;
$aData[-1] = $sA2;
next;
}
last;
}
}
printf "%s %s\n", @aData[0,1];
@aData = ();
}
close ($fhFileB);
复制代码
输出结果如下:
Q12 Babushkin
D23 Azov
Y11 Aznakayevo
U10 Balashikha Balashov
Q45 Babayevo
A11 Bagrationovsk
R08 Babayevo
ZAA Babayevo
复制代码
作者:
sunzhiguolu
时间:
2015-12-04 19:08
回复
20#
patagonia2
将代码的第 6 行:
'File A Path'
,
'File B Path'
替换成你自己的文件路径!
作者:
substr函数
时间:
2015-12-04 20:56
回复
19#
stanley_tam
大神 [
]
加好友
作者:
substr函数
时间:
2015-12-04 21:29
回复
13#
stanley_tam
大神
大神我想问一个
感觉
如果
if ($num < $min) {
# only need to look for numbers greater than $num
my $new_num = $num;
while (1) {
$new_num += 1;
if (exists $a_data_href->{$new_num}) {
$words_aref = $a_data_href->{$new_num};
last;
}
}
}
复制代码
可以
if ($num < $min) {
$words_aref = $a_data_href->{$min};
}
复制代码
我的理解哪里有偏差? 还请大神指点...
谢谢大神
作者:
stanley_tam
时间:
2015-12-05 10:42
多谢大神指点
真是众里寻他千百度,蓦然回首。。。
sub find_the_nearest {
# body...
my ($num, $a_data_href, $max, $min) = @_;
my $words_aref = [];
if (exists $a_data_href->{$num}) {
# if exactly matched
$words_aref = $a_data_href->{$num};
}
else {
if ($num < $min) {
$words_aref = $a_data_href->{$min};
}
elsif ($num > $max){
$words_aref = $a_data_href->{$max};
}
else {
# look for numbers both way
my $new_num_bigger = $num;
my $new_num_smaller = $num;
while (1) {
$new_num_bigger += 1;
$new_num_smaller -= 1;
my @words = ();
if (exists $a_data_href->{$new_num_bigger}) {
push @words, @{ $a_data_href->{$new_num_bigger} };
}
if (exists $a_data_href->{$new_num_smaller}) {
push @words, @{ $a_data_href->{$new_num_smaller} };
}
if (scalar @words) {
$words_aref = \@words;
last;
}
}
}
}
return $words_aref;
}
复制代码
回复
24#
substr函数
欢迎光临 Chinaunix (http://bbs.chinaunix.net/)
Powered by Discuz! X3.2