Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python数组的高效交叉_Python - Fatal编程技术网

python数组的高效交叉

python数组的高效交叉,python,Python,我不知道如何在这两个阵列之间相交: a = [[125, 1], [193, 1], [288, 23]] b = [[108, 1], [288, 1], [193, 11]] result = [[288,24], [193, 12]] 所以交集由第一个元素求和,数组的第二个元素求和,有没有办法有效地做到这一点 好吧,我犯了一个错误,没有解释我关于效率的意思,对不起。考虑以下幼稚的实现: a = [[125, 1], [193, 1], [288, 23]] b = [[108, 1],

我不知道如何在这两个阵列之间相交:

a = [[125, 1], [193, 1], [288, 23]]
b = [[108, 1], [288, 1], [193, 11]]

result = [[288,24], [193, 12]]
所以交集由第一个元素求和,数组的第二个元素求和,有没有办法有效地做到这一点

好吧,我犯了一个错误,没有解释我关于效率的意思,对不起。考虑以下幼稚的实现:

a = [[125, 1], [193, 1], [288, 23]]
b = [[108, 1], [288, 1], [193, 11]]
result = {}
for i, j in a:
    for k, l in b:
        if i == k:
            result[i] = j + l
print result
所以我试图找到一种更有效的方法来解决我的问题,从某种意义上说,更符合Python。所以我需要你的帮助

尝试以下测试用例(我的代码也在其中):

运行时间:28.6980509758
result = []
ms, mb = (dict(a),dict(b)) if len(a)<len(b) else (dict(b),dict(a))
for k in ms:
  if k in mb:
    result.append([k,ms[k]+mb[k]])
ms,mb=(dict(a),dict(b))如果len(a)使用计数器:

c_sum = Counter()
c_len = Counter()
for elt in a:
    c_sum[elt[0]] += elt[1]
    c_len[elt[0]] += 1

for elt in b:
    c_sum[elt[0]] += elt[1]
    c_len[elt[0]] += 1

print [[k, c_sum[k]] for k, v in c_len.iteritems() if v > 1]
给你

a = [[125, 1], [193, 1], [288, 23]]
b = [[108, 1], [288, 1], [193, 11]]
for e in a:
    for e2 in b:
        if e[0] == e2[0]:
            inter.append([e[0], e[1]+e2[1]])
print inter
输出

[[193, 12], [288, 24]]

如果您还希望统计列表中的重复项,则此解决方案有效

from collections import defaultdict

a = [[125, 1], [193, 1], [288, 23]]
b = [[108, 1], [288, 1], [193, 11]]

d = defaultdict(int)

for value, num in a+b:
    d[value] += num
result = filter(lambda x:x[1]>1, d.items())
result = map(list, result)  # If it's important that the result be a list of lists rather than a list of tuples
print result
# [[288, 24], [193, 12]]

首先,Python没有数组。它有列表。只是名字的问题,但可能会让人困惑。这方面的一个班轮是:

[ [ae[0],ae[1]+be[1]] for be in b for ae in a if be[0] == ae[0] ]

PS:正如您所说的“交叉点”,我假设列表设置为(“包”,真的),并且作为包,它们被正确地规范化(即,它们没有重复的元素/键)。

这些数据似乎最好存储为字典

da = dict(a)
db = dict(b)
一旦你有了它,你就可以:

result = [[k, da[k] + db[k]] for k in set(da.keys()).intersection(db.keys())]
或者在Python2.7中,您也可以使用
viewkeys
而不是set

result = [[k, da[k] + db[k]] for k in da.viewkeys() & db]

假设a和b的唯一性,我会这样做:

k = {} # store totals
its = {} # store intersections
for i in a + b:
    if i[0] in k:
        its[i[0]] = True
        k[i[0]] += i[1]
    else:
        k[i[0]] = i[1]
# then loop through intersections for results
result = [[i, k[i]] for i in its]
我得到:


在我的笔记本电脑上运行的时间是O(len(a)+len(b)),大约是0.02秒,而在你的笔记本电脑上运行的时间是18.79秒。我还确认它返回的结果与算法中的
result.items()
相同。

此解决方案可能不是最快的,但可能是最简单的实现,因此为了完整性,我决定发布它

aa = Counter(dict(a))
bb = Counter(dict(b))
cc = aa + bb
cc
=> Counter({288: 24, 193: 12, 108: 1, 125: 1})

list(cc.items())
=> [(288, 24), (193, 12), (108, 1), (125, 1)]
如果必须仅包括公用密钥:

[ (k, cc[k]) for k in set(aa).intersection(bb) ]
=> [(288, 24), (193, 12)]

numpy
serachsorted()
argsort()
intersect1d()
都是可能的替代方案,而且速度非常快。此示例还应考虑非唯一第一元素问题

>>> import numpy as np
>>> a=np.array([[125, 1], [193, 1], [288, 23]])
>>> b=np.array([[108, 1], [288, 1], [193, 11]])
>>> aT=a.T
>>> bT=b.T
>>> aS=aT[0][np.argsort(aT[0])]
>>> bS=bT[0][np.argsort(bT[0])]
>>> i=np.intersect1d(aT[0], bT[0])
>>> cT=np.hstack((aT[:,np.searchsorted(aS, i)], bT[:,np.searchsorted(bS, i)]))
>>> [[item,np.sum(cT[1,np.argwhere(cT[0]==item).flatten()])] for item in i]
[[193, 12], [288, 24]] #not quite happy about this, can someone comes up with a vectorized way of doing it?


如果一个元素中有两个匹配的元素,那么行为应该是什么?它们也应该被汇总吗?例如,
a=[[100,1],[100,2]
b=[[50,1]]]
我不知道我会将此数据作为列表列表保存。也许一本字典或更好的计数器会更有意义。如果你认真使用“高效”这个词,你尝试过哪些替代方法,以及为什么它们的性能不够好?此外,也是非常重要的,数据集的大小是多少?@badc0re似乎有一个关于使用表达性(以及易于编写、测试和理解的)语言功能提高效率的争论(也非常重要)。你为什么不帮我们解决这个案子?你能对不同的答案进行测试并计时并发布吗?@badc0re你的期望是什么?为什么29秒不好?这是非常重要的。大多数有经验的开发人员都会逐步提高性能(并降低可读性),直到性能可以接受,而不是更高一点。他们珍惜自己的时间和其他开发人员的时间,因为他们可能会遇到他们的代码。也许你错过了问题中的“高效”一词?我认为O(n^2)算法不合格。我认为OP使用“高效”一词只是出于习惯。或者无知。如果他真的这么想的话,他会详细说明列表的大小、一般的时间限制、他用计时信息尝试过的其他解决方案,甚至他为什么使用Python而不是其他语言。OP很可能不太关心解决方案的时间复杂性。由于他们没有表现出任何改进基本解决方案的尝试,而只是针对他们的问题提出一个一般性的问题。一句话被高估了,这尤其没有效率当你理解他们时,他们有一个重要的位置。如果您非常担心性能,那么您在用Python开发什么呢?与其他语言相比,它的主要优势在于表达能力,而不是性能。请不要到处诋毁语言的一个重要部分,阻止人们学习它。让他们自己得出结论。在这种情况下,我认为性能差别不大。你给他们计时了吗?这无法回答OP提出的问题。这是没有效率的。反对这种语言并不能减轻你的解决方案是一种低效的算法。效率与问题有关。如果你认为“有表现力”和“不如其他语言有效”是反对Python的论据,那么你是对的。对我来说,第一个是支持Python的,第二个只是陈述了一个事实。我同意,对于小数据集,您的解决方案工作得很好,而且很有表现力。然而,OP多次写道,需要一种有效的算法。这让我相信,也许这些名单会非常庞大。算法的大O符号是n*m。可以做得更好,但仍保持表达能力。我也不同意这样的说法,即仅仅因为有人在用python编写代码,他们就不关心性能。我没有投反对票,您的解决方案到目前为止的最佳性能是0.01240801122.nice!pythonic和efficientAlso伟大的性能(0.0174601078033),但我没有得到its[i[0]]=True部分。当它第二次击中键/id时,它意味着它是相交的,然后我们存储它,而不是进行另一个循环,只是为了确定它是否是相交。很抱歉,我意识到我错过了[]在上一句话中。还添加了一些很好的优化,以防您有一个数组非常小的数据,只有我的2个百分点。在我的笔记本电脑上,这非常快,速度为0.0067秒,验证结果与原始结果相符。我认为它的可读性也很好。做得好!性能将取决于
a
b
数组的维度,请参阅本文:
>>> import numpy as np
>>> a=np.array([[125, 1], [193, 1], [288, 23]])
>>> b=np.array([[108, 1], [288, 1], [193, 11]])
>>> aT=a.T
>>> bT=b.T
>>> aS=aT[0][np.argsort(aT[0])]
>>> bS=bT[0][np.argsort(bT[0])]
>>> i=np.intersect1d(aT[0], bT[0])
>>> cT=np.hstack((aT[:,np.searchsorted(aS, i)], bT[:,np.searchsorted(bS, i)]))
>>> [[item,np.sum(cT[1,np.argwhere(cT[0]==item).flatten()])] for item in i]
[[193, 12], [288, 24]] #not quite happy about this, can someone comes up with a vectorized way of doing it?