4

我有一个非常大的文本文件(几 GB),其格式如下:

1 2
3 4
3 5
3 6
3 7
3 8
3 9

文件已排序,双行已删除。我想删除重复的对,例如“2 1”、“4 3”相反的顺序。有没有人有任何解决方案可以在资源非常有限的环境中使用 BASH、AWK、perl 或任何类似语言?我无法加载整个文件并在值之间循环。

4

7 回答 7

4

您想删除第二个数字小于第一个数字的行吗?

perl -i~ -lane'print if $F[0] < $F[1]' file
于 2012-10-18T21:11:05.663 回答
3

可能的解决方案:

  • 扫描文件
  • 对于第二个值小于第一个值的任何对,交换两个数字
  • 按第一个然后第二个数字再次对对进行排序
  • 删除重复项

我仍在考虑在磁盘扫描方面更有效的解决方案,但这是一种基本的幼稚方法

于 2012-10-18T21:20:58.403 回答
2

对于每个值,对硬盘驱动器上的文件执行二进制搜索,而不将其加载到内存中。如果看到重复项,请删除它。然后进行最后一次传递,删除两个或更多的所有实例\n

于 2012-10-18T21:11:44.270 回答
2

不完全确定这是否有效/是否有任何好处...

awk '{ if ($2 > $1) print; else print $2, $1 }' hugetext | sort -nu -O hugetext
于 2012-10-18T22:18:06.493 回答
1

你想删除重复考虑1 22 1是相同的吗?

< file.in \
| perl -lane'print "@F[ $F[0] < $F[1] ? (0,1,0,1) : (1,0,0,1) ]"' \
| sort -n \
| perl -lane'$t="@F[0,1]"; print "@F[2,3]" if $t ne $p; $p=$t;' \
> file.out

这可以处理任意大的文件。

于 2012-10-18T21:27:05.483 回答
0
perl -lane '
    END{
        print for sort {$a<=>$b} keys %h;
    }

    $key = $F[0] < $F[1] ? "$F[0] $F[1]" : "$F[1] $F[0]";
    $h{$key} = "";
' file.txt

说明

  1. 我按数字顺序对当前行进行排序
  2. $key我通过将第一个值和第二个值与空格连接来创建哈希键变量
  3. 我定义了$hash{$key}
  4. 最后,我打印按数字顺序排序的所有键。

哈希键本质上是唯一的,所以没有重复。

您只需要使用Unix重定向来创建一个新文件。

于 2012-10-18T21:21:43.723 回答
0

这是一个通用的 O(n) 算法,可以在 1 遍中执行此操作(不需要循环或排序):

  1. 从一个空的哈希集作为你的黑名单开始(一个集是一个只有键的映射)
  2. 一次读取一行文件。
  3. 对于每一行:
    • 检查这对已经在您的黑名单中。
    • 如果是这样,请忽略它。
    • 如果没有,请将其附加到您的结果文件中;并将交换后的值添加到黑名单中(例如,如果您刚刚将“3 4”和“4 3”读到黑名单中)

这需要 O(n) 时间来运行,并且需要 O(n) 存储黑名单。(如果您将文件作为 r/w 操作以在对照黑名单检查行时删除行,则无需额外存储结果)

于 2012-10-18T21:25:41.757 回答