繁体   English   中英

如何在列表中选择特定的交集元素? 类型错误:未散列类型:“列表”

[英]How can I choose a specific intersection element in a list? TypeError: unhashed type: 'list'

我想交叉两个列表并打印它们的共同点。 但是,我想选择要相交的特定元素(例如[0][hockeymatch][1]等)。 对于 x[0] 或 y[1],我的意图不是匹配整行 select,而是只匹配 select [hockeymatch]。 我收到此错误:

TypeError: unhashable type: 'list'

在我的代码示例中,我想得到这个 output:

'Seattle-Minnesota', 'NHL', '18:00'

所以我只喜欢“西雅图-明尼苏达”、“NHL”、“18:00”,没有:

  • 没有 [1.33] 和 [62.0],因为这些数字不同于 [2.5] 和 [125.0],尽管它们包含在另一个“Seattle-Minnesota”、“NHL”、“18:00”中
  • 没有“Dallas-Arizona”、“NHL”、“15:00”和“Vancouver-Vegas”、“NHL”、“20:00”,因为它们与“Seattle-Minnesota”、“NHL”是两个不同的游戏, '18:00'

重要提示:这只是一个示例,但我会添加更多曲棍球比赛。 我不想仅通过设置 [('Seattle-Minnesota', 'NHL', '18:00')] 来手动打印,但我想“自动”打印任何共同的曲棍球比赛,甚至不止一场如果有的话,共同匹配)。

更新:对于 x[0] 或 y[1],我的意图不是 select 整场比赛,而是 select 仅 [hockeymatch],例如('Dallas-Arizona', 'NHL', '15: 00 ')] 或所有其他匹配项。 我想要一种方法能够将 select [hockeymatch]、[number1]、[number2] 与比赛放在同一行。

简单来说,我的意思是:

“考虑到将来会添加其他曲棍球比赛,寻找一个或多个常见的比赛(即 [hockeymatch]),但从交集 [number1] 和 [number2] 中排除”

代码:

#x = []
#x.append([[hockeymatch], [number1], [number2]])
x = [[[('Dallas-Arizona', 'NHL', '15:00')], [1.75], [87.5]],
     [('Seattle-Minnesota', 'NHL', '18:00')], [2.5], [125.0]]

#y = []
#y.append([[hockeymatch], [number1], [number2]])
y = [[[('Seattle-Minnesota', 'NHL', '18:00')], [1.33], [62.0]],
       [('Vancouver-Vegas', 'NHL', '20:00')], [0.50], [43.0]]

test = list(set(x[0]).intersection(y[0]))
print(test)

PS:为了使代码更加清晰,我在创建列表时添加了注释以及如何使用 append 插入元素

#x = []
#x.append([[hockeymatch], [tournament], [number1], [number2]])
x = [[[('Dallas-Arizona', 'NHL', '15:00')], [1.75], [87.5]],
[('Seattle-Minnesota', 'NHL', '18:00')], [2.5], [125.0]]

#y = []
#y.append([[hockeymatch], [tournament], [number1], [number2]])
y = [[[('Seattle-Minnesota', 'NHL', '18:00')], [1.33], [62.0]],
[('Vancouver-Vegas', 'NHL', '20:00')], [0.50], [43.0]]

t1 = []
t2 = []

for i in range(len(x)):
     if i == 0:
          t1.append(tuple(x[i][0]))
     else:
          try:
               if len(x[i][0]) == 3:
                    t1.append(tuple(x[i]))
          except:
               pass

for i in range(len(y)):
     if i == 0:
          t2.append(tuple(y[i][0]))
     else:
          try:
               if len(y[i][0]) == 3:
                    t2.append(tuple(y[i]))
          except:
               pass

print(list((set(t1).intersection(set(t2)))))

您可以使用函数简化代码

x = [[[('Dallas-Arizona', 'NHL', '15:00')], [1.75], [87.5]],
[('Seattle-Minnesota', 'NHL', '18:00')], [2.5], [125.0]]


y = [[[('Seattle-Minnesota', 'NHL', '18:00')], [1.33], [62.0]],
[('Vancouver-Vegas', 'NHL', '20:00')], [0.50], [43.0]]

t1 = []
t2 = []

def matches(your_l, l_used):
     for i in range(len(l_used)):
          if i == 0:
               your_l.append(tuple(l_used[i][0]))
          else:
               try:
                    if len(l_used[i][0]) == 3:
                         your_l.append(tuple(l_used[i]))
               except:
                    pass

matches(t1, x)
matches(t2, y)

print(list((set(t1).intersection(set(t2)))))

它应该是:

list(set(x[1]).intersection(y[0][0]))
#[('Seattle-Minnesota', 'NHL', '18:00')]

因为 x 和 y 是嵌套列表。 因此,当您直接在 2D 列表上应用set()时会出错。

TypeError: unhashable type: 'list'

根据文档:

集合是不同的可散列对象的无序集合。 这些对象必须是可散列的,以便查找、添加和删除元素比每次执行这些操作时查看每个单独的元素更快。

列表不是可散列的(/不可变的)数据类型。 这意味着当您尝试将 x[0] 转换为一个集合时,您需要确保 x[0] 中的每个元素都是可哈希的(元组、集合等而不是列表)。 您可以将 x[0] 从列表更改为元组。 (圆括号而不是方括号)使事情正常进行。

此外,对于不需要更改(至少就地更改)的数据使用元组通常是个好主意。

x = [((('Dallas-Arizona', 'NHL', '15:00')), 1.75, 87.5), ...

编辑

进行此更改后,假设您要查找存储在 x 和 y 中的匹配项之间的共同匹配项。 你可以试试

    x = [
        (('da', 'nhl', '15:00'), 1.75, 87.5),
    (('sm', 'nhl', '18:00'), 2, 3)
]

y = [
        (('da', 'nhl', '15:00'), 1.75, 87.5),
        (('sm', 'nhl', '18:00'), 2, 3),
        (('fse', 'afww', '15:00'), 121.75, 187.5),
        (('afae', 'awfwa', '18:00'), 21, 13)

]
x_set = set(x)
y_set = set(y)
common_matches = x_set.intersection(y_set)
print([match[0] for match in common_matches])

这应该打印:

[('da', 'nhl', '15:00'), ('sm', 'nhl', '18:00')]

可变list让你很伤心。

让我们使用一些不可变的tuple

from collections import namedtuple
from operator import itemgetter

Game = namedtuple("Game", "match, league, time, num1, num2")

x = [
    Game("Dallas-Arizona", "NHL", "15:00", 1.75, 87.5),
    Game("Seattle-Minnesota", "NHL", "18:00", 2.5, 125.0),
]
y = [
    Game("Seattle-Minnesota", "NHL", "18:00", 1.33, 62.0),
    Game("Vancouver-Vegas", "NHL", "20:00", 0.50, 43.0),
]


def getter(n: int, games: list[Game]):
    return list(map(itemgetter(n), games))


print(getter(0, x))
print(getter(0, y))

print("\nintersection:")
print(set(getter(0, x)) & set(getter(0, y)))
print("\nunion:")
print(set(getter(0, x)) | set(getter(0, y)))

output:

['Dallas-Arizona', 'Seattle-Minnesota']
['Seattle-Minnesota', 'Vancouver-Vegas']

intersection:
{'Seattle-Minnesota'}

union:
{'Seattle-Minnesota', 'Dallas-Arizona', 'Vancouver-Vegas'}

显示set时,如果您查看 output 的sorted(... )版本,通常会更容易阅读。


您的问题没有为业务概念命名,例如前三个字段表示什么或两个数字的含义。

如果愿意,您可以定义一个 3 元组,然后定义一个包含它的更大的命名元组。 如果您对其进行测试并发现它解决了您的用例,请随时发布此类源代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM