【发布时间】:2011-02-13 05:50:34
【问题描述】:
我遇到了一个问题,即在一个范围内查找缺失值,并且该范围对于连续的行也是可变的。
输入
673 673 673 676 676 680 2667 2667 2668 2670 2671 2674输出应该是这样的
674 675 677 678 679 2669 2672 2673这只是一部分,行值还可以更多 如果您需要任何澄清,请告诉我。
【问题讨论】:
我遇到了一个问题,即在一个范围内查找缺失值,并且该范围对于连续的行也是可变的。
这只是一部分,行值还可以更多 如果您需要任何澄清,请告诉我。
【问题讨论】:
纯 bash。
使用两个子shell并运行diff,然后清理结果。
diff <(cat my_range_with_holes) <(seq 1 1000) | grep '>' | cut -c 3-
【讨论】:
在 Python 中:
def report_missing_numbers(f):
for line in f:
numbers = [int(n) for n in line.split()]
all_numbers = set(range(numbers[0], numbers[-1]))
missing = all_numbers - set(numbers)
yield missing
注意:all_numbers有点假,因为范围不包括最终的数字,但由于该数字保证在集合中,不影响正确性算法。
注意:我从原始答案中删除了 [-1],因为 int(n) 不关心尾随的 '\n'。
【讨论】:
file 是内置名称,请勿将其用作变量。
.split() 不会因意外的双空格而中断:'1 2'.split() -> ['1', '2'] 但'1 2'.split(' ') -> ['1', '', '2']。 int() 不适用于空字符串。
split() 上回复投票和提示。在昏暗的过去的某个时候,我曾经知道,但我忘记了。
Perl:
use Modern::Perl;
for my $line (<DATA>) {
chomp $line;
my @numbers = split /\s+/, $line;
my ($min, $max) = (sort { $a <=> $b } @numbers)[0, -1];
my @missing = grep { not $_ ~~ @numbers } $min .. $max;
say join " ", @missing;
}
__DATA__
673 673 673 676 676 680
2667 2667 2668 2670 2671 2674
【讨论】:
Python:
for line in open("inputfile.txt"):
vals = set(map(int, line.split()))
minv, maxv = min(vals), max(vals)
missing = [str(v) for v in xrange(minv + 1, maxv) if v not in vals]
print " ".join(missing)
【讨论】:
itertools.imap 而不是map。
使用 Perl 的示例代码:
#!/usr/bin/perl
use strict;
use warnings;
my @missing;
while(<DATA>) {
my @data = split (/[ ]/, $_);
my $i = shift @data;
foreach (@data) {
if ($_ != ++$i) {
push @missing, $i .. $_ - 1;
$i = $_;
}
}
}
print join " ", @missing;
__DATA__
673 673 673 676 676 680
2667 2667 2668 2670 2671 2674
输出
674 675 677 678 679 2669 2672 2673
【讨论】:
鲁比:
$stdin.each_line do |line|
numbers = line.scan(/\d+/).map(&:to_i)
missing = (numbers.min..numbers.max).to_a - numbers
puts missing.join " "
end
高尔夫版(79 个字符):
puts $stdin.map{|l|n=l.scan(/\d+/).map(&:to_i);((n.min..n.max).to_a-n).join" "}
【讨论】:
纯猛击:
while read -a line ; do
firstvalue=${line[0]}
lastvalue=${line[${#line[@]}-1]}
output=()
# prepare the output array
for (( item=firstvalue; item<=lastvalue; item++ )); do
output[$item]=1
done
# unset array elements with an index from the input set
for item in ${line[@]}; do
unset "output[$item]"
done
# echo the remaining indices
echo -e "${!output[@]}"
done < "$infile"
【讨论】:
Perl 单行器:
perl -anE'($a,$b)=@F[0,-1];$,=" ";@h{@F}=();say grep!exists$h{$_},$a..$b'
【讨论】:
修改 Marcelo 的解决方案,在发生异常时安全释放文件句柄:
with open('myfile.txt') as f:
numbers = [int(n) for n in f.readline()[:-1].split(' ')]
all_numbers = set(range(numbers[0], numbers[-1]))
missing = all_numbers - set(numbers)
这也避免了使用内置名称file。
【讨论】:
使用 Bash、sort、uniq 和 jot (Mac OS X) 的 Shell 解决方案:
numbers="673 673 673 676 676 680"
numbers="2667 2667 2668 2670 2671 2674"
sorted=($(IFS=$'\n' echo "${numbers}" | tr " " '\n' | sort -u ))
low=${sorted[0]}
high=${sorted[@]: -1}
( printf "%s\n" "${sorted[@]}"; jot $((${high} - ${low} + 1)) ${low} ${high} ) | sort | uniq -u
【讨论】:
Bash 解决方案:
cat file_of_numbers| xargs -n2 seq | sort -nu
【讨论】:
a = [ 673, 673, 673, 676, 676, 680]
def woo(a):
max_, min_ = a[0:-1]
a = set(a)
tot = set(list(range(min_,max_+1)))
return list( tot - a )
你有你的清单。 集合运算符对于比较列表很有用。在您的情况下,您希望找到以下所有元素:
Set 运算符生成来自列表的所有唯一值
要选择tot 中但不在a 中的所有值,只需执行tot - a。只需将输出格式化为列表
如果您想将a 保存为一个列表,您需要在您的函数中使用copy():
a = [ 673, 673, 673, 676, 676, 680]
def woo(a):
max_, min_ = a[0:-1]
a = set(a.copy())
tot = set(list(range(min_,max_+1)))
return list( tot - a )
【讨论】: