【问题标题】:How to efficiently compare two maps?如何有效地比较两张地图?
【发布时间】:2017-09-21 08:31:51
【问题描述】:

我需要比较 2 张地图,我正在寻找最好的方法。特别是,给定输入中的两个映射,我需要确定至少 80% 的条目是否相同。目前的做法是:

-数据以key->value的形式存储在两个文件中。

例如:

1.1.1.0/24| 178 188 198

1.1.2.0/24| 199 2212 2999 212 ....

在这个文件中存储了大约 600K 条目。

-将条目上传到地图中,然后进行比较。

由于数据量很大,执行速度很慢。 (我需要多次执行这种比较)。我什至不知道地图是否是最好的数据结构。考虑到 2 个文件中的条目数可能不同(第一个文件中的某些条目可能不存在于第二个文件中,反之亦然),并且文件中的条目按字母顺序排序。我正在使用 Python。

两种不同的方法:

1)上传包含元组的集合后,比较执行如下:

def checkSame(bgpt1, bgpt2):
    size1 = len(bgpt1)
    size2 = len(bgpt2)

    num_shared_ip = float(len(bgpt1 & bgpt2))
    ratio = num_shared_ip / max(size1, size2)
    return ratio

2) 使用映射通过迭代进行比较:

def compareMaps(map1,map2):
    counter=0
    for keyM1 in map1:
         if keyM1 in map2:
            if map2[keyM1]==map1[keyM1]:
                counter+=1
    ...

【问题讨论】:

  • 请显示您当前方法的代码。
  • 刚刚编辑过。,无论如何我不需要实现,只是想知道如何提高性能
  • 什么是“非常慢”,什么是可接受的时间量?
  • 它必须更高效,无需考虑时间
  • return num_shared_ip / max(size1, size2) 使用的 CPython 操作码少于 ratio = num_shared_ip / max(size1, size2); return ratio。你去 - 它更有效,只是。 (是的,你需要推理时间,我不是无缘无故问这个。)

标签: python algorithm performance data-structures


【解决方案1】:

由于您的文件已排序,因此您不必存储它们,甚至不必在行外解析它们。您可以使用较小的当前元素继续按顺序前进:

def count_equal(a, b):
    """
    Counts the number of values that are equal in two sorted iterables.

    >>> odds = [1, 3, 5, 7, 9, 11, 13, 15]
    >>> primes = [2, 3, 5, 7, 11, 13]
    >>> count_equal(odds, primes)
    5
    """
    return _count_equal(iter(a), iter(b))


def _count_equal(a, b):
    c = 0
    x = next(a)
    y = next(b)

    try:
        while True:
            while x < y:
                x = next(a)

            while y < x:
                y = next(b)

            if x == y:
                c += 1
                x = next(a)
                y = next(b)
    except StopIteration:
        return c

您可以在同一读取中分别跟踪每个文件中有多少行:

from __future__ import division


class CountingIterable:
    def __init__(self, iterable):
        self.iterable = iterable

    def __iter__(self):
        count = 0

        for x in self.iterable:
            yield x
            count += 1

        self.count = count


with open('file1.txt', 'r') as a, open('file2.txt', 'r') as b:
    a_counter = CountingIterable(a)
    b_counter = CountingIterable(b)

    a_iterator = iter(a_counter)
    b_iterator = iter(b_counter)

    n = count_equal(a_iterator, b_iterator)

    # consume any remaining elements to acquire count
    for _ in a_iterator: pass
    for _ in b_iterator: pass

    result = n / max(a_counter.count, b_counter.count)

【讨论】:

  • 简单的合并成功!
【解决方案2】:

由于您没有发布任何代码,我可以尝试提出一些想法。

也许您可以尝试merge sort 这两个文件,然后将每一行与下一行进行比较(这需要每个文件都有一个唯一的键)。对于每次命中,您可以将计数器更新一,当您最终到达文件末尾时,您将除以行数以获得相似度。

另一个想法是计算 Jaccard 相似度,但这要求每个文件都有唯一的值并且您的数据适合内存。从两个文件中读取所有值并创建 (key:value) 字符串集。 (Set 表示每个值的基数为 1)。然后你可以使用这个函数:

def compute_jaccard_index(set_1, set_2):
    n = len(set_1.intersection(set_2))    
    return n / float(len(set_1) + len(set_2) - n)

返回关于两个集合的相似程度的标准化索引 [0 - 1]。

编辑:刚刚看到您发布的代码。按照我的建议,在元组集上尝试Jaccard Index。您也可以使用ready implementations for Jaccard Index 之一

【讨论】:

    猜你喜欢
    • 2014-09-08
    • 2011-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-05-17
    • 2022-01-10
    • 2016-06-25
    • 1970-01-01
    相关资源
    最近更新 更多