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

Question:

I would like to intersect two lists and print what they have in common. However, I would like to choose the specific element to intersect (e.g. [0] or [hockeymatch], [1], etc). With x[0] or y[1], my intention is not to select the entire line of the match, but to select only [hockeymatch]. I get this error:

TypeError: unhashable type: 'list'

In my code example, I would like to get this output:

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

So I would just like ‘Seattle-Minnesota’, ‘NHL’, ’18:00′, without:

  • without [1.33] and [62.0], because these numbers are different from [2.5] and [125.0] despite being contained in another ‘Seattle-Minnesota’, ‘NHL’, ’18:00′
  • without ‘Dallas-Arizona’, ‘NHL’, ’15:00′ and ‘Vancouver-Vegas’, ‘NHL’, ’20:00′, because they are two different games from ‘Seattle-Minnesota’, ‘NHL’, ’18:00′

IMPORTANT: This is just an example, but I will add more hockey matches. I don’t want to manually print by setting only [(‘Seattle-Minnesota’, ‘NHL’, ’18:00′)], but I would like to "AUTOMATICALLY" print any hockey match in common, even more than one match in common if there is one).

UPDATE: With x[0] or y[1], my intention is not to select the entire line of the match, but to select only [hockeymatch], for example (‘Dallas-Arizona’, ‘NHL’, ’15:00 ‘)] or all of the other matches. I wanted a way to be able to select [hockeymatch], [number1], [number2] in the same line as the match.

In simple terms, I meant:

"considering that other hockey matches will be added in the future,
look for one or more common matches (i.e. [hockeymatch]), but exclude
from the intersection [number1] and [number2]"

Code:

#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)

P.S: For greater clarity of the code I have added the comments of when I create the list and how I insert the elements with append

Asked By: Takao貴男

||

Answers:

#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)))))

You can simplify the code by using functions

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)))))

Answered By: Vikash

According to documentation:

A set is an unordered collection of distinct hashable objects. The
objects have to be hashable so that finding, adding and removing
elements can be done faster than looking at each individual element
every time you perform these operations.

A list is not a hashable(/immutable) data-type. That means when you try to cast x[0] into a set, you need to make sure every element in x[0] is hashable (tuples, sets, etc not lists). You could change x[0] from a list to a tuple. (rounded parenthesis instead of square brackets) to make things work.

Also, it is generally a good idea to use tuples for data that does not need to be changed, at least in place.

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

Edit

After making this change, say you want to find the common matches between matches stored in x and y.
You can try

    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])

This should print:

[('da', 'nhl', '15:00'), ('sm', 'nhl', '18:00')]
Answered By: Navneet Desai

Mutable lists are causing you grief.

Let’s use some immutable tuples!

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'}

When displaying a set,
the output will usually be a bit easier to read
if you view the sorted( ... )
version of it.


Your question didn’t give names to the business
concepts, like what the 1st three fields denote
or what the two numbers are all about.

If you like, you could define a 3-tuple
and then define a bigger named tuple
which includes it. Please feel free
to post
such source code if you test it and find
it addresses your use case.

Answered By: J_H

It should be:

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

Since x and y are nested lists. So, you were getting error when you were applying set() directly on 2D list.

TypeError: unhashable type: 'list'
Answered By: Talha Tayyab