Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/286.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_List_Numpy - Fatal编程技术网

Python 在列表中匹配相反数字的出现

Python 在列表中匹配相反数字的出现,python,list,numpy,Python,List,Numpy,我有一份这样的清单 results = [100, 100, -100, 100, -100, -100] 我想找出第一个出现的相反数字。所以第一个100将与第一个100相匹配,第二个100将与第二个100相匹配 我希望获得以下职位: [0, 2], [1, 4], [3, 5] i、 e:[0,2]表示结果[0]和结果[2],其中第一次出现的100与第一次出现的-100匹配 编辑:您可以假设总是有相同数量的正/负数据,并且列表仅包含1个数字 任何帮助都将被告知这应该有效: results

我有一份这样的清单

results = [100, 100, -100, 100, -100, -100]
我想找出第一个出现的相反数字。所以第一个100将与第一个100相匹配,第二个100将与第二个100相匹配

我希望获得以下职位:

[0, 2], [1, 4], [3, 5]
i、 e:
[0,2]
表示
结果[0]
结果[2]
,其中第一次出现的100与第一次出现的-100匹配


编辑:您可以假设总是有相同数量的正/负数据,并且列表仅包含1个数字

任何帮助都将被告知

这应该有效:

results = [100, 100, -100, 100, -100, -100]

solution = []
for i, x in enumerate(results):
    if x > 0 and isinstance(x, int):
        y = results.index(-x)
        results[results.index(-x)] = 'found'
        solution.append([i,y])

print solution

这也适用于出现不同数字的一般情况:

solutions = []
for x in set(abs(x) for x in results):
    solutions += list(zip([i for i, x2 in enumerate(results) if x2 == x],
                          [i for i, x2 in enumerate(results) if x2 == x*-1]))

我们可以分两个阶段有效地做到这一点。在分析阶段,我们过滤出正数,对它们进行排序并按索引进行分组,如:

from itertools import groupby

subresult = dict(map(lambda x:(x[0],iter(tuple(x[1]))),
                     groupby(sorted(filter(lambda x:x[1] < 0,enumerate(results)),
                             key=lambda x:x[::-1]),lambda x:x[1])
            ))
这将产生:

>>> subresult = dict(map(lambda x:(x[0],iter(tuple(x[1]))),groupby(sorted(filter(lambda x:x[1] < 0,enumerate(results)),key=lambda x:x[::-1]),lambda x:x[1])))
>>> [[i,next(subresult[-v])[0]] for i,v in enumerate(results) if v > 0]
[[0, 2], [1, 4], [3, 5]]
subresult=dict(map(lambda x:(x[0],iter(tuple(x[1])),groupby(sorted(filter)(lambda x:x[1]<0,enumerate(results)),key=lambda x:x[::-1]),lambda x:x[1])) >>>[[i,next(子结果[-v])[0]]如果v>0,则枚举(结果)中的i,v为[[i,next(子结果[-v])] [[0, 2], [1, 4], [3, 5]]
通常,由于字典查找和我们使用迭代器(这样就可以对我们所在的索引进行簿记),这将非常有效。

对于列表仅包含2个整数(
x
-x
)的简单情况,您可以简单地将索引组合在一起:

indexes = [[],[]]
for i,x in enumerate(results):
    indexes[0].append(i) if x > 0 else indexes[1].append(i)
list(zip(*indexes))
例如:

>>> results = [100, 100, -100, 100, -100, -100]
>>> indexes = [[],[]]
>>> for i,x in enumerate(results): indexes[0].append(i) if x > 0 else indexes[1].append(i)
... 
>>> list(zip(*indexes))
[(0, 2), (1, 4), (3, 5)]
注:对于小输入,2个单独的列表理解(例如,
[i代表i,x>0时枚举(结果)中的x]
可能比在
循环中追加
要快。

pos={}
pos = {}
for i,item in enumerate(results ):
    if item < 0: continue 
    if item not in pos:
       pos[item] = []
    pos[item].append(i)

[ [pos[-item].pop(0), i] for i,item in enumerate(results ) if item < 0]  

[[0, 2], [1, 4], [3, 5]]
对于i,枚举中的项目(结果): 如果项目<0:继续 如果项目不在pos中: pos[项目]=[] pos[项目].追加(一) [[pos[-item].pop(0),i]表示i,如果项<0,则枚举(结果)中的项] [[0, 2], [1, 4], [3, 5]]
IMO,最快的方法(对于大输入)应该是以下方法(尽管,我的解决方案不假设输入列表只包含一个值及其相反的值,因此如果添加该假设,可以使其更快):

输出:

Unsorted solution: [(1, 2), (0, 4), (3, 5)]
Sorted solution: [(0, 4), (1, 2), (3, 5)]
[(0, 2), (1, 4), (3, 5)]

这个简单的基于观察的方法怎么样?使用列表理解将其分为两个列表,然后按照您想要的顺序进行排序

使用列表理解

In [18]: neg_list = [idx for idx, el in enumerate(results) if el < 0]
In [19]: pos_list = [idx for idx, el in enumerate(results) if el > 0]

In [20]: neg_list
Out[20]: [2, 4, 5]

In [21]: pos_list
Out[21]: [0, 1, 3]

In [22]: list(zip(pos_list, neg_list))
Out[22]: [(0, 2), (1, 4), (3, 5)]
In [24]: neg_gen = (idx for idx, el in enumerate(results) if el < 0)
In [25]: pos_gen = (idx for idx, el in enumerate(results) if el > 0)

In [27]: list(zip(pos_gen, neg_gen))
Out[27]: [(0, 2), (1, 4), (3, 5)]

# on 2nd run, there won't be any element in the generator.
In [28]: list(zip(pos_gen, neg_gen))
Out[28]: []

注意:您也可以使用
生成器理解
来获得相同的结果,但请注意,将生成器转换为列表一次后,它将被耗尽

使用生成器理解

In [18]: neg_list = [idx for idx, el in enumerate(results) if el < 0]
In [19]: pos_list = [idx for idx, el in enumerate(results) if el > 0]

In [20]: neg_list
Out[20]: [2, 4, 5]

In [21]: pos_list
Out[21]: [0, 1, 3]

In [22]: list(zip(pos_list, neg_list))
Out[22]: [(0, 2), (1, 4), (3, 5)]
In [24]: neg_gen = (idx for idx, el in enumerate(results) if el < 0)
In [25]: pos_gen = (idx for idx, el in enumerate(results) if el > 0)

In [27]: list(zip(pos_gen, neg_gen))
Out[27]: [(0, 2), (1, 4), (3, 5)]

# on 2nd run, there won't be any element in the generator.
In [28]: list(zip(pos_gen, neg_gen))
Out[28]: []
[24]中的
:neg_gen=(如果el<0,则idx表示idx,el表示枚举(结果)
In[25]:pos_gen=(如果el>0,则idx表示idx,el表示枚举(结果)中的el)
In[27]:列表(zip(pos_gen,neg_gen))
Out[27]:[(0,2)、(1,4)、(3,5)]
#在第二次运行时,发电机中不会有任何元件。
In[28]:列表(zip(pos_gen,neg_gen))
Out[28]:[]

对于
结果只包含两个不同整数的示例情况:

import numpy as np

results = np.array([100, 100, -100, 100, -100, -100])

output = list(zip(np.where(results > 0)[0], np.where(results < 0)[0]))


时间是
~0.002
对于
结果*1000

说输入是
[2,2,3,-2,-3,-2]
3
是否与第一个
-3
匹配(或者已经移出窗口)。此外,如果没有这样的相反情况,该怎么办?您可以假设总是有相同数量的正/负,并且总是1个数字(因此没有出现2和3,只有2个)“零根本不会出现吗?”WillemVanOnsem no 0s。@StevenG:你测试的
结果的大小是多少?
如果列表很小,这不是一个测试东西的好方法。我在结果*1000上做的,zipa得到了0.626999855042,Roelant解决方案得到了0.00200009346008。很好的方法和效率,我得到了0.0049秒with结果*1000@timgeb:我写了多行,每行都有评论。谢谢,工作结果*1000速度是0.003994850159非常快速和优雅!结果的速度*1000是0。00200009346008@StevenG谢谢;经过反思,如果您定义
pos=abs(结果[0]),可能会更快;neg=-pos
首先,然后使用
=
而不是
实际上,非常快,必须对结果进行测试*10000才能看到最快的结果…这是最快和最灵活的方法之一one@StevenG只有当第一个要素是积极的,每一个快速,对利昂和克里斯的最佳结果_Rands@StevenG添加的numpy还有一个版本。请看一看look@StevenG:添加了一个完整的基于
numpy
的解决方案。请查看!
In [24]: neg_gen = (idx for idx, el in enumerate(results) if el < 0)
In [25]: pos_gen = (idx for idx, el in enumerate(results) if el > 0)

In [27]: list(zip(pos_gen, neg_gen))
Out[27]: [(0, 2), (1, 4), (3, 5)]

# on 2nd run, there won't be any element in the generator.
In [28]: list(zip(pos_gen, neg_gen))
Out[28]: []
import numpy as np

results = np.array([100, 100, -100, 100, -100, -100])

output = list(zip(np.where(results > 0)[0], np.where(results < 0)[0]))
[(0, 2), (1, 4), (3, 5)]