【问题标题】:How do I find a value relative to where a list occurs within my list in Python?如何在 Python 的列表中找到相对于列表出现位置的值?
【发布时间】:2017-01-30 02:44:48
【问题描述】:

我有一个数字列表:

Data = [0,2,0,1,2,1,0,2,0,2,0,1,2,0,2,1,1,...]

我有一个两个元组的列表,这是上面各个数字的所有可能组合:

Combinations = [(0,0),(0,1),(0,2),(1,0),(1,1),(1,2),(2,0),(2,1),(2,2)]

我想尝试查找 Combinations 中的每个项目在 Data 中出现的位置,并将每次出现后的值添加到另一个列表中。

例如,对于 (0,2),我想创建一个列表 [0,0,0,1],因为这些值是紧接在 Data 中出现 (0,2) 之后的值。

到目前为止,我有:

any(Data[i:i+len(CurrentTuple)] == CurrentTuple for i in xrange(len(Data)-len(CurrentTuple)+1))

其中CurrentTupleCombinations.pop()。 问题是这只会给我一个布尔值,判断 CurrentTuple 是否出现在 Data.xml 中。我真正需要的是Data中每次出现后的值。

有没有人知道如何解决这个问题?谢谢!

【问题讨论】:

  • 如果您需要更快的东西(我想如果您使用的是 markov-chain,就是这种情况)请查看我下面的答案...避免append 可以更快地生成列表。跨度>

标签: python list tuples markov-chains


【解决方案1】:

您可以使用 dict 对数据进行分组,以查看原始列表中的位置/是否有任何梳子:

it1, it2 = iter(Data), iter(Data)
next(it2)

Combinations = [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]

d = {c: [] for c in Combinations}
ind = 2
for i, j in zip(it1, it2):
    if (i, j) in d and ind < len(Data):
        d[(i, j)].append(Data[ind])
    ind += 1
print(d)

这会给你:

{(0, 1): [2, 2], (1, 2): [1, 0], (0, 0): [], (2, 1): [0, 1], (1, 1): [2], (2, 0): [1, 2, 1, 2], (2, 2): [], (1, 0): [2], (0, 2): [0, 0, 0, 1]}

你也可以反过来做:

from collections import defaultdict

it1, it2 = iter(Data), iter(Data)
next(it2)
next_ele_dict = defaultdict(list)
data_iter = iter(Data[2:])
for ind, (i, j) in enumerate(zip(it1, it2)):
    if ind < len(Data) -2:
      next_ele_dict[(i, j)].append(next(data_iter))

def next_ele():
    for comb in set(Combinations):
        if comb in next_ele_dict:
           yield comb, next_ele_dict[comb]

print(list(next_ele()))

这会给你:

 [((0, 1), [2, 2]), ((1, 2), [1, 0]), ((2, 1), [0, 1]), ((1, 1), [2]), ((2, 0), [1, 2, 1, 2]), ((1, 0), [2]), ((0, 2), [0, 0, 0, 1])]

任何方法都比为组合中的每个元素遍历数据列表更好。

要处理任意长度的元组,我们只需要根据长度创建元组:

from collections import defaultdict

n = 2

next_ele_dict = defaultdict(list)

def chunks(iterable, n):
    for i in range(len(iterable)-n):
        yield tuple(iterable[i:i+n])

data_iter = iter(Data[n:])
for tup in chunks(Data, n):
      next_ele_dict[tup].append(next(data_iter))

def next_ele():
    for comb in set(Combinations):
        if comb in next_ele_dict:
            yield comb, next_ele_dict[comb]


print(list(next_ele()))

您可以将其应用于您喜欢的任何实现,就制作元组而言,逻辑将是相同的。

【讨论】:

  • 这个只有在你想比较几个数字时才有效
  • @RiccardoPetraglia 如果你只考虑非重叠对,(0,2),它可以很容易地适应另一种情况,但由于 OP 只考虑三种情况的(0, 2) 发生然后他们一定不能]
  • 是的,但如果你决定比较数字的“三元组”,他写的内容也有效
  • @RiccardoPetraglia,你在这个问题中看到了什么? 我有一个包含两个元组的列表
  • @RiccardoPetraglia,OP 可能希望在我们验证不存在的内容之前先验证他们的预期输出;)
【解决方案2】:
sum([all(x) for x in (Data[i:i+len(CurrentTuple)] == CurrentTuple for i in xrange
(len(Data)-len(CurrentTuple)+1))])

您所做的返回生成以下列表的生成器:

[array([False,  True], dtype=bool),
 array([ True, False], dtype=bool),
 array([False,  True], dtype=bool),
 ...
 array([False, False], dtype=bool),
 array([False, False], dtype=bool),
 array([False, False], dtype=bool),
 array([False,  True], dtype=bool)]

仅当数组中的bool 都是True 时,您在此列表中的一个数组与CurrentTuple 匹配。仅当列表的所有元素都是 True 时,all 才会返回 True,因此只有当数字孪生与 CurrentTuple 匹配时,[all(x) for x in ...] 生成的列表才会包含 True。当您使用 sum 时,True 将转换为 1。我希望很清楚。

如果您只想比较非重叠对:

[2,2,
 0,2,
 ...]

并保持算法尽可能通用,您可以使用以下内容:

sum([all(x) for x in (Data[i:i+len(CurrentTuple)] == CurrentTuple for i in xrange
(0,len(Data)-len(CurrentTuple)+1,len(CurrentTuple)))])

尽管更加神秘,但这段代码比使用 append 的任何替代代码都要快得多(查看 [Comparing list comprehensions and explicit loops (3 array generators faster than 1 for loop) 了解原因)。

【讨论】:

    猜你喜欢
    • 2012-01-18
    • 1970-01-01
    • 1970-01-01
    • 2021-08-10
    • 2018-05-08
    • 2017-10-18
    • 2017-01-02
    • 2017-01-26
    • 2020-03-22
    相关资源
    最近更新 更多