匹配两个字符串列表之间的根的算法

时间:2013-05-07 14:27:49

标签: algorithm

问题:

我正在使用监视服务来监视目录以进行输入,因此一旦我有两个(半)匹配的输入文件,我就可以触发一个事件。我遇到的问题是:如果我有两个列表,每个列表包含可能不同的字符串,我怎样才能在列表发现时找到匹配的根。

文件名结构如下所示:

<companyname>-<ordernum><postfix>.csv

所以例如:

list1 could contain: 
    mycomp-1234.csv
    mycomp-4567.csv
    newcomp-7891.csv
    oldcomp-3376.csv

list2 could contain:
    mycomp-2232_items.csv
    newcomp-13123_items.csv
    oldcomp-87078777_items.csv
    mycomp-1234_items.csv

我想找到,并在列表之间发生匹配时立即触发事件。匹配是任何文件名,少于后缀。即mycomp-1234将返回两个列表的匹配。

我在寻找什么

我希望找到最有效的方式来做到这一点。我知道我可以迭代每个列表比较值,但我相信有更有效的方法来做到这一点。

我不需要代码,我宁愿自己学习,所以推动正确的方向是完美的。如果你的手指让你编写代码,请编写伪代码,以便它可以使尽可能多的语言受益。

不,这不是功课。对于那些非常好奇的人来说,这是执行从csv到X12 EDI文件的EDI转换。

3 个答案:

答案 0 :(得分:3)

按字母顺序对列表进行排序,然后比较值并在列表中具有较小值的步骤中前进。如果列表中有任何共同的元素,则值将匹配。

答案 1 :(得分:2)

两个排序列表的并排比较。

Collections.sort(list1);
Collections.sort(list2);
int i1 = 0;
int i2 = 0;
while (i1 < list1.size() && i2 < list.size()) {
    String name1 = list1.get(i1);
    String name2 = list2.get(i2);
    String[] parts1 = name1.split("[-_.]");
    String[] parts2 = name2.split("[-_.]");
    if (parts1.length < 3) {
        ++i1;
        continue;
    }
    if (parts2.length < 3) {
        ++i2;
        continue;
    }
    int cmp = parts1[0].compareTo(parts1[0]);
    if (cmp == 0) {
        cmp = parts1[1].compareTo(parts1[1]);
    }
    if (cmp < 0) {
        ++i1;
        continue
    }
    if (cmp > 0) {
        ++i2;
        continue
    }
    // Found match:
    ...
    ++i1;
    ++i2;
}

答案 2 :(得分:-1)

在线方法:维护包含所有当前文件名的二叉搜索树。用作文件名相关位的键。例如,newcomp-7891.csvnewcomp-7891_items的密钥为newcomp-7891。每次监视服务报告目录事件时,您都可以删除废弃的名称,并可以尝试向树中添加新名称。如果某个密钥已在树中,则触发您想要的活动。

如果散列实现支持在删除文件名时删除密钥,则可以类似地使用散列表。

这个问题要求“以最有效的方式做到这一点”。请注意,此方法比每次发生目录事件时从头开始排序列表更有效。在具有k个添加和删除的事件中,如果数据集具有n个条目,则它使用O(k·lg n)时间,因此在u目录事件中,在平均树大小为n并且发生m添加/删除的一段时间内,它会做O(m·lg n)工作。相比之下,在其他答案中建议的排序 - 每次方法将做O(u·n·lg n)工作,这是更多。