【问题标题】:Finding indices of matches between a list and multiple sublists in Python在 Python 中查找列表和多个子列表之间的匹配索引
【发布时间】:2018-02-20 20:16:54
【问题描述】:

针:['', 'yes', 'yes', '', '', '', 'yes', 'yes', 'yes', '']

干草堆:[['', '', 'yes', 'yes', '', '', 'yes', 'yes', '', 'yes'], ['', '', '', 'yes', 'yes', '', '', '', 'yes', 'yes']]

Needle 在 2、6、7 处与 Haystack[0] 匹配,在 8 处与 Haystack[1] 匹配,我希望能够创建这些索引匹配列表。

目前:我的代码返回 [1,2,6,7,8],并没有告诉我匹配在哪里......不确定为什么它会在 1 找到匹配:

for sublist in (haystack):
print(needle)
print(sublist)
print([i for i, item in enumerate(needle) if item in sublist and item != ''])

我的输出看起来像

['', 'yes', 'yes', '', '', '', 'yes', 'yes', 'yes', '']
['', '', 'yes', 'yes', '', '', 'yes', 'yes', '', 'yes']
[1, 2, 6, 7, 8]
['', 'yes', 'yes', '', '', '', 'yes', 'yes', 'yes', '']
['', '', '', 'yes', 'yes', '', '', '', 'yes', 'yes']
[1, 2, 6, 7, 8]

完全可重现:

needle = ['', 'yes', 'yes', '', '', '', 'yes', 'yes', 'yes', '']
haystack = [['', '', 'yes', 'yes', '', '', 'yes', 'yes', '', 'yes'], ['', '', '', 'yes', 'yes', '', '', '', 'yes', 'yes']]`

for sublist in (haystack):
    print(needle)
    print(sublist)
    print([i for i, item in enumerate(needle) if item in sublist and item != ''])

【问题讨论】:

  • 您说的是“对于针中的项目,如果干草堆中的“是”(这总是正确的)打印针中“是”的索引......所以[1,2,6,7,8] 将是回答至少包含 1 个 "yes" 的任何干草堆

标签: python list search match


【解决方案1】:

使用enumerate zip:

for sublist in haystack:
    print(needle)
    print(sublist)
    print([i for i, (x, y) in enumerate(zip(needle, sublist)) if x and y and x == y])

输出:

['', 'yes', 'yes', '', '', '', 'yes', 'yes', 'yes', '']
['', '', 'yes', 'yes', '', '', 'yes', 'yes', '', 'yes']
[2, 6, 7]
['', 'yes', 'yes', '', '', '', 'yes', 'yes', 'yes', '']
['', '', '', 'yes', 'yes', '', '', '', 'yes', 'yes']
[8]

【讨论】:

  • 可能是 x!='' and y!='' 会更明确(+1 虽然 zip + enumerate)
【解决方案2】:

正如 TemporalWolf 指出的那样,我列举了错误的事情......以下工作!

for sublist in (haystack):
    print([i for i, item in enumerate(sublist) if needle[i]=='yes' and sublist[i]=='yes'])

【讨论】:

  • 在我看来,在另一个循环等中进行枚举的整个方法非常繁琐且令人困惑(效率低下+对于该代码的未来读者来说不清楚),特别是如果这里真正发生的事情很简单数组之间的逻辑与。我在下面建议了另一个答案,供您考虑。
【解决方案3】:

你在找什么-

needle = ['', 'yes', 'yes', '', '', '', 'yes', 'yes', 'yes', '']
haystack = [['', '', 'yes', 'yes', '', '', 'yes', 'yes', '', 'yes'],
['', '', '', 'yes', 'yes', '', '', '', 'yes', 'yes']]

for sublist in (haystack):
    print(needle)
    print(sublist)
    print([i for i, item in enumerate(needle) if item == sublist[i] and item != ''])

【讨论】:

  • @user61871。将您的“if item in sublist”更改为 if“item == sublist[i]”。
【解决方案4】:

如果我理解正确,那么您正在寻找数组之间的逻辑与,其中"yes"1""0

因此,如果我们首先将您的数据转换为二进制:(当然,您可以跳过本段并假设我们首先有二进制数据...)

import numpy as np
def convert_to_binary(arr):
  return 1 * (np.array(arr) == 'yes')
needle = convert_to_binary(needle)
# array([0, 1, 1, 0, 0, 0, 1, 1, 1, 0])
haystack = np.array([convert_to_binary(h_arr) for h_arr in haystack])
# array([[0, 0, 1, 1, 0, 0, 1, 1, 0, 1],
#        [0, 0, 0, 1, 1, 0, 0, 0, 1, 1]])

他们的逻辑与:

their_logical_and = needle & haystack
# array([[0, 0, 1, 0, 0, 0, 1, 1, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0, 0, 1, 0]])

要实现非零索引,可以使用numpy.nonzero

indices = [list(np.nonzero(arr)[0]) for arr in their_logical_and]
# [[2, 6, 7], [8]]

【讨论】:

  • 感谢您的反馈,@TemporalWolf。缩进到底在哪里搞砸了?如果您指的是我的第一段代码,那么整个段落都是多余的,正如我在上面所写的那样,为了完整起见(将 OP 的原始数据转换为更方便的二进制格式),以简短的写作形式(但没有搞砸)。
  • 啊,我没仔细看。我不鼓励使用内联函数定义,尽管它是正确的。
  • 好吧,我编辑了它以使其更清晰。但这无论如何都不是重要的部分。这里的重要观察是 OP 真的想在数组之间进行逻辑与(请参阅我对他的回答的评论)。所以任何循环/枚举/压缩等都是多余和混乱的。
猜你喜欢
  • 2013-03-28
  • 1970-01-01
  • 2023-03-24
  • 2015-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多