Counting occurences in a list of tuples

I am trying to run through each element of each tuple in this list to check for the word ‘Rome’ and print a total.
image

It clearly is running through each tuple and giving me the unaltered ‘total’ variable from before the for loop was run. But it doesn’t appear to be running through each element of each tuple…or maybe it is and i’m not asking it to show me what it’s finding.

Is the system for counting incorrect here?

city is simply a counter that’s controlling your loop.

To see what it’s doing, introduce the print(city) function to your loop.

Also, moving forward, please don’t post screen shots; rather post your code like this:

```python
your code
```

edit: scrub that, I didn’t read your code correctly.

connections = [
    ('Amsterdam', 'Dublin', 100),
    ('Amsterdam', 'Rome', 140),
    ('Rome', 'Warsaw', 130),
    ('Minsk', 'Prague', 95),
    ('Stockholm', 'Rome', 190),
    ('Copenhagen', 'Paris', 120),
    ('Madrid', 'Rome', 135),
    ('Lisbon', 'Rome', 170),
    ('Dublin', 'Rome', 170),
    ]

total = 0
for city in connections:
    if city == 'Rome':
        total = total +1
    print(total)

My apologies.

No worries. I’m unsure how to unpack that, off of the top of my head.

you need to add another for ... loops to iterate over the member of the tuples

connections = [
    ("Amsterdam", "Dublin", 100),
    ("Amsterdam", "Rome", 140),
    ("Rome", "Warsaw", 130),
    ("Minsk", "Prague", 95),
    ("Stockholm", "Rome", 190),
    ("Copenhagen", "Paris", 120),
    ("Madrid", "Rome", 135),
    ("Lisbon", "Rome", 170),
    ("Dublin", "Rome", 170),
]

total = 0
for city in connections:
    for target in city:
        if target == "Rome":
            total = total + 1
    print(total)
1 Like

As @gunungpw has shown: city is now iterating over the connections list and target is iterating over the tuple within said list.

If you are trying to count the tuples with “Rome” inside, then:

In [2]: sum("Rome" in conn for conn in connections)
Out[2]: 6

Or, if you are trying to sum the values from the “Rome” tuples (it’s not clear)

In [3]: sum(conn[2] for conn in connections if "Rome" in conn)
Out[3]: 935

So if I’m understanding the logic here, the initial “for” loop is only running through the list of tuples and I need an additional “for” loop for the contents of the tuple itself?

Thank you!

Im sorry, I’m too new to python for this jedi mind trick :grinning:

1 Like

Broken down a bit more:

  • Each item is a tuple, so checking city == "Rome" will alway be False, because a tuple will never equal a string. But you can use the in operator to check if a tuple has a string value inside:
    >>> "Rome" in ("Rome", "Amsterdam", 100)
    True
    
  • The sum function adds up sequences:
    >>> sum([1,2,3,4])
    10
    
  • In numerical contexts, boolean True counts as “1” and False counts as “0”:
    >>> sum([True, False, True])
    2
    
  • The fancy part: ["Rome" in conn for conn in connections] is list comprehension, which is a compact way to build up sequences. This one makes a list that has True if “Rome” is in a tuple, and False if it is not:
    >>> ["Rome" in conn for conn in connections]  # conn is a tuple
    [False, True, True, False, True, False, True, True, True]
    
  • Putting together: sum("Rome" in conn for conn in connections) is the same as sum([False, True, True, False, True, False, True, True, True]) which is 6.

I slightly skipped a bit about leaving off the square brackets in the call to sum. Technically, that makes it a generator expression rather than a list comprehension. The only tangible difference is that the generator expression is “lazy evaluated” and so a concrete intermediate list is never actually constructed. That might be useful to save memory if you have, say, a sequence of hundreds of millions of connections to chew through.

Thank you! I really appreciate the breakdown and it makes sense. I’ll be diving deeper into list comprehension later in the course but I understand enough of what you said for brain comprehension lol. I’m still learning to walk (and at my age, with a busted hip and a bum knee).

My next step is to get the sum of the integers in the list of tuples so i would assume it is similar to the previous syntax bit wit a “total=total+num” instead of the +1. My problem now is getting the “if” statement to only accept numbers or else it errors on the strings.

Yes to add the value in num to total use one of these two statements:
a) total = total + num
b) total += num
For your use-case they are equivalent.


I am not sure why @gduque deleted his post. I think it was useful for you. Normally you would want to iterate the connections like this:

for *cities, num in connections:
    ...

Let us know if you understand what is going on in this for loop. Hint: print the two variables inside the loop.


Im sorry i dont have the characters on my phone to paste the actual code right now. Ill paste it tonight if need be.

This errors because there are strings in the tuple as well so im trying to slice the inside loop to the only index point with integers and im getting this error. Not sure how to tell it to only iterate through the integers.

No, it is telling you this error because you are asking Python to evaluate num[1], which does not exist. In the line above it, you are telling that it should iterate numbers and store every element in a new variable tup. Here you are saying “evaluate num[1] and store every element of tup in the resulting variable”. But it cannot find num.

Let us do some code:

>>> numbers =[("fish", 12), ("pork", 10), ("beef", 46)]
>>> for tup in numbers:
...     print(tup)
... 
('fish', 12)
('pork', 10)
('beef', 46)

So each tup is a tuple (duh!), which is indexed and iterable. So we can say:

>>> for tup in numbers:
...     print(tup[1])
... 
12
10
46

This works of course because the first item in each tuple is a string and the second is a number. We can make use of this by counting as follows:

>>> total = 0
>>> for tup in numbers:
...     total += tup[1]
... 
>>> total
68

…which is what we hoped for.

Printing the values is one way of print debugging; it may also be handy to look at the types of variables. Like so:

>>> print(type(numbers))
<class 'list'>
>>> for tup in numbers:
...     print(type(tup))
... 
<class 'tuple'>
<class 'tuple'>
<class 'tuple'>

Thank you for breaking this down so well! I was incorrect in my earlier assumption that the first iteration didn’t run through the tuples in the list. I see what you mean about checking your assumtion by printing!

I was able to break the code down more simply without an inner loop:

connections = [
    ('Amsterdam', 'Dublin', 100),
    ('Amsterdam', 'Rome', 140),
    ('Rome', 'Warsaw', 130),
    ('Minsk', 'Prague', 95),
    ('Stockholm', 'Rome', 190),
    ('Copenhagen', 'Paris', 120),
    ('Madrid', 'Rome', 135),
    ('Lisbon', 'Rome', 170),
    ('Dublin', 'Rome', 170),
    ]

count = 0
total = 0
for city in connections:
    if city[1] == 'Rome':
            count = count+1
            total += city[2]

print(count, "connections lead to Rome with an average flight time of", total//count, "minutes")
1 Like

Nicely done.

There are any number of ways you could expand on this, which would also expand your skills. One way, would be to have two inputs:

destination = input("Destination? ")

departure = input("Departure? ")

… then have your app return a route between them. An an example, a user could choose to travel from Dublin to Rome via Amsterdam or direct.

If you had a list of cities, like this:

cities = ['Amsterdam', 'Dublin', 'Rome', 'Warsaw', 'Minsk', 'Prague', 'Stockholm', 'Copenhagen', 'Paris', 'Madrid', 'Lisbon']

… you could use something like this:

for index, city in enumerate(cities, 1):
    print(f"{index}: {city}")

… so that a user could then enter a number, rather than having to type the city name, then have your app figure out the route between departure and destination, and calculate the flight duration.

You could even .sort() the cities, alphabetically, so that Warsaw is number 11, rather than number 4

I would also use f-strings on the output:

print(f"{count} connections lead to Rome with an average flight time of {total//count} minutes")

Just some suggestions for you.

You’ve initialized each tuple in a list, and construct a single loop like “for city in connections: “, which deals with the whole tuple like “(‘Amsterdam’, ‘Dublin’, 100)” as a single index and couldn’t find.

All you need to do is to initialize nested loop, which deals with each tuple’s index in a list.