我有两个文件A-nodes_to_deleteB-nodes_to_keep。每个文件都有一个多线路用数字ID。

我想有数字ID是在nodes_to_delete列表但不是在nodes_to_keep,例如 “替代文字”

PostgreSQL数据库内做这是不合理的慢。任何整洁的方式使用Linux命令行工具来完成它在bash?

更新:这似乎是一个Python化的工作,但这些文件是真的,真的很大。我已经解决了使用uniqsort有的集理论技术的一些类似的问题。这是关于大小的两个或三个数量级比数据库当量更快。

有帮助吗?

解决方案

COMM 命令这样做的。

其他提示

有人告诉我如何做的正是这SH一两个月前,然后我找不到它一会儿......边看我无意中发现你的问题。在这里它是:

set_union () {
   sort $1 $2 | uniq
}

set_difference () {
   sort $1 $2 $2 | uniq -u
}

set_symmetric_difference() {
   sort $1 $2 | uniq -u
}

使用comm - 它会比较两个排序的文件一行行

简短的回答你的问题

此命令将返回独特deleteNodes线,但在不keepNodes线。

comm -1 -3 <(sort keepNodes) <(sort deleteNodes)

示例设置

让我们来创建文件命名keepNodesdeleteNodes,并用它们作为comm命令无序输入。

$ cat > keepNodes <(echo bob; echo amber;)
$ cat > deleteNodes <(echo bob; echo ann;)

默认情况下,此布局运行COMM不带参数的打印3列:

lines_unique_to_FILE1
    lines_unique_to_FILE2
        lines_which_appear_in_both

使用以上,运行COMM我们的示例文件,而无需参数。注意三列。

$ comm <(sort keepNodes) <(sort deleteNodes)
amber
    ann
        bob

柱抑制方法输出

禁止塔1,2或3 -N;注意,当该列被隐藏,空白收缩起来。

$ comm -1 <(sort keepNodes) <(sort deleteNodes)
ann
    bob
$ comm -2 <(sort keepNodes) <(sort deleteNodes)
amber
    bob
$ comm -3 <(sort keepNodes) <(sort deleteNodes)
amber
    ann
$ comm -1 -3 <(sort keepNodes) <(sort deleteNodes)
ann
$ comm -2 -3 <(sort keepNodes) <(sort deleteNodes)
amber
$ comm -1 -2 <(sort keepNodes) <(sort deleteNodes)
bob

排序是非常重要的!

如果你没有第一分拣文件的执行通讯时,与正常关于哪些文件未排序的消息失败。

comm: file 1 is not in sorted order

comm是专为这种用途的情况下设计的,但它需要排序的输入。

awk可以说是这方面的一个更好的工具,因为它是相当直截了当找差集,不需要sort,并提供额外的灵活性。

awk 'NR == FNR { a[$0]; next } !($0 in a)' nodes_to_keep nodes_to_delete

也许,例如,要找到仅在表示非负数线的区别是:

awk -v r='^[0-9]+$' 'NR == FNR && $0 ~ r {
    a[$0]
    next
} $0 ~ r && !($0 in a)' nodes_to_keep nodes_to_delete

也许你需要更好的方法来做到这一点Postgres里,我几乎可以打赌,你不会找到一个更快的方法使用平面文件来做到这一点。你应该可以做一个简单的内部连接,并假设这两个ID的cols被索引,应该是非常快的。

所以,这是从其他答案稍有不同。我不能说一个C ++编译器是一个准确的“Linux CLI工具”,但运行g++ -O3 -march=native -o set_diff main.cpp(与下面main.cpp可以执行特技代码):

#include<algorithm>
#include<iostream>
#include<iterator>
#include<fstream>
#include<string>
#include<unordered_set>

using namespace std;

int main(int argc, char** argv) {
    ifstream keep_file(argv[1]), del_file(argv[2]);
    unordered_multiset<string> init_lines{istream_iterator<string>(keep_file), istream_iterator<string>()};
    string line;
    while (getline(del_file, line)) {
        init_lines.erase(line);
    }
    copy(init_lines.begin(),init_lines.end(), ostream_iterator<string>(cout, "\n"));
}

要使用时,只需运行set_diff B A A B,由于Bnodes_to_keep)和所得到的差将被打印到标准输出。

请注意,我已经放弃了几个C ++最佳实践,以保持代码简单。

许多另外的速度优化可以由(在多个存储器的价格)。 mmap也将是大的数据集是特别有用的,但是这会使代码更多地参与。

既然你提到的数据集都很大,我认为每次读nodes_to_delete行可能是一个好主意,以减少内存消耗。如果有很多在你nodes_to_delete愚弄的在上面的代码采用的方法不是特别有效。另外,为了不保留。


东西更容易复制并粘贴到bash(即跳跃main.cpp的创建):

g++ -O3 -march=native -xc++ -o set_diff - <<EOF
#include<algorithm>
#include<iostream>
#include<iterator>
#include<fstream>
#include<string>
#include<unordered_set>

using namespace std;

int main(int argc, char** argv) {
        ifstream keep_file(argv[1]), del_file(argv[2]);
        unordered_multiset<string> init_lines{istream_iterator<string>(keep_file), istream_iterator<string>()};
        string line;
        while (getline(del_file, line)) {
                init_lines.erase(line);
        }
        copy(init_lines.begin(),init_lines.end(), ostream_iterator<string>(cout, "\n"));
}
EOF
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top