Python Forum
Looping through a dictionary for every other value
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Looping through a dictionary for every other value
#1
Hi,
I am trying to find every other value in a dictionary. This is my thought process:

01) Create a loop to go through the dictionary's index.
02) Use a if statement to run a test with % to see if the result is even or odd
03) If the result is not even then I will append this value to a new list.

Here is the code (just trying to see it print before I start appending

odd = ()
for a in (letlist.index):
    if ((a % 2) != 0):
        print (a)
Returned: for a in (letlist.index):
TypeError: 'builtin_function_or_method' object is not iterable

I then tried this
odd = ()
for a in (letlist):
    if ((a % 2) != 0):
        print (a)
Returned: if ((a % 2) != 0):
TypeError: not all arguments converted during string formatting

So then I tried this (trying to make it simpler)
odd = ()
for a in (letlist):
    a = letlist.index
    if (a % 2):
        print (a)
That returned: if (a % 2):
TypeError: unsupported operand type(s) for %: 'builtin_function_or_method' and 'int'

Not sure what i am doing wrong. Is the logic that I wrote in how to solve the problem right? If so what is wrong with my implementation of it?

Thanks.
Reply
#2
Quote:I am trying to find every other value in a dictionary.
Do you mean a list? As this doesn't make much sense for a dictionary.

If you mean a list, the easiest way is slicing:
>>> my_list
['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> my_list[::2]
['a', 'c', 'e', 'g']
>>> for letter in my_list[::2]:
...     print(letter)
...
a
c
e
g
>>>
Edit:
Okay realized that was a typo and you mean even/odd.
You have basically the right idea:
>>> my_list
[6, 9, 8, 3, 5, 1, 10, 10, 4, 6]
>>> for num in my_list:
...     if num % 2:
...         print(num)
...
9
3
5
1
>>> [num for num in my_list if num % 2]
[9, 3, 5, 1]
>>>
Reply
#3
It is for dictionary, This is the challenge i was given.

Here is the complete code. I am now running into issues with the original dictionary being out of scope and then new problems when I try to use global.

Complete code as it stands
mport string
letlist = list(string.ascii_lowercase)


#Create string of letters
letstring = string.ascii_lowercase

#Create list of numbers
list1=[]
for i in range (1, 27):
    list1.append(i)

#Create dictionary for part 1
def dictfunc():
    global zipped
    zipped = dict(zip(list1,letlist))

dictfunc()


def test ():
    for a in zipped:
        return a[::2]
    print (a)
Errors:
File "C:/Users/c0unt3rpl4y/PycharmProjects/House/scratchpad.py", line 26, in <module>
test()
File "C:/Users/c0unt3rpl4y/PycharmProjects/House/scratchpad.py", line 23, in test
return a[::2]
TypeError: 'int' object is not subscriptable

I am really new to this so I keep googling various ideas and then taking snippets of code and throwing them in and trying to make them work.

I will try it your way now and see if that works better

Your code snipped

for num in zipped:
    if num % 2:
        print(num)
Does indeed return the odds numbers but it does not return every other value of the dictionary which is the final piece of it. I think I need to maybe use index?
Reply
#4
Quote:it does not return every other value of the dictionary
Every other value of a dictionary doesn't really make sense.
Also, consider the global keyword off limits for the next 5 years or so; seriously.
It should not be used for anything like this.

Please provide the exact text of the challenge you are trying to solve.

>>> from string import ascii_lowercase as lower
>>> my_dict = dict(zip(lower, range(1,27)))
>>> my_dict
{'a': 1, 'c': 3, 'b': 2, 'e': 5, 'd': 4, 'g': 7, 'f': 6, 'i': 9, 'h': 8, 'k': 11, 'j': 10, 'm': 13, 'l': 12, 'o': 15, 'n': 14, 'q': 17, 'p': 16, 's': 19, 'r': 18, 'u': 21, 't': 20, 'w': 23, 'v': 22, 'y': 25, 'x': 24, 'z': 26}
>>> odd_entries = {k:v for k,v in my_dict.items() if v % 2}
>>> odd_entries
{'a': 1, 'c': 3, 'e': 5, 'g': 7, 'i': 9, 'k': 11, 'm': 13, 'o': 15, 'q': 17, 's': 19, 'u': 21, 'w': 23, 'y': 25}
>>>
Reply
#5
Complete text of challenge:

1) Start with this list: ['a', 'b', 'c', ..., 'z'}
And create a function that turns it into this dictionary: {1: 'a', 2: 'b', 3: 'c', ..., 26: 'z'}

2) Start with this string: 'abc...z'
And create a function that turns it into this dictionary: {1: 'a', 2: 'b', 3: 'c', ..., 26: 'z'}

3) Take one of the above functions and include only the odd numbers / letters: {1: 'a', 3: 'c', ..., 25: 'y'}

Complete code for part 1 & 2 (part 3 is what i am trying to solve).

#Create list of letters
import string
letlist = list(string.ascii_lowercase)

#Create string of letters
letstring = string.ascii_lowercase

#Create list of numbers
list1=[]
for i in range (1, 27):
    list1.append(i)

#Create dictionary for part 1
def dictfunc():
    zipped =dict(zip(list1,letlist))

dictfunc()

#Create dictionary for part 2
def dictfun2():
    zipped2 = dict(zip(list1, letstring))

dictfun2()
If I don't use global I get an error about the dictionary not being found. My guess is somehow it is local in scope to the function that is why i tried using global.

Really appreciate all the help.

Adding this snippet

odd_entries = {k:v for k,v in zipped.items() if v % 2}
print (odd_entries)
Returns an error I've never seen before (good chance I screwed up something in the code above because some of it I didnt understand specically the k:v part.)

Traceback (most recent call last):
File "C:/Users/c0unt3rpl4y/PycharmProjects/House/scratchpad.py", line 21, in <module>
odd_entries = {k:v for k,v in zipped.items() if v % 2}
File "C:/Users/c0unt3rpl4y/PycharmProjects/House/scratchpad.py", line 21, in <dictcomp>
odd_entries = {k:v for k,v in zipped.items() if v % 2}
TypeError: not all arguments converted during string formatting
Reply
#6
Communication with functions should be done via argument passing and return values. Not global variables.
from string import ascii_lowercase as lower


def string_to_dict():
    return dict(zip(range(1,27), lower))


def odds_only():
    my_dict = string_to_dict()
    return {k:v for k,v in my_dict.items() if k % 2}


print(odds_only())
Reply
#7
This totally solved it. The way you write code is amazing man. It is so graceful and compact. One last question. What is the k:v part I don't really understand that. Most specifically the v part.

Complete code for anyone who cares:

#Let's impress Doctor Housman. Instead of writing out the lists manually lets do it programatically shall we?
#Create list of letters
import string
letlist = list(string.ascii_lowercase)

#Create string of letters
letstring = string.ascii_lowercase

#Create list of numbers
list1=[]
for i in range (1, 27):
    list1.append(i)

#Create dictionary for part 1
def dictfunc():
    zipped =dict(zip(list1,letlist))

dictfunc()

#Create dictionary for part 2
def dictfun2():
    zipped2 = dict(zip(list1, letstring))

dictfun2()

def odds_only():
    my_dict = dictfunc()
    return {k: v for k, v in my_dict.items() if k % 2}

print(odds_only())
Next up is to edit the code to make it work using enumerate and then to edit that again to make it work using loops that involve counting.

Thanks for all the help everyone!
Reply
#8
That is a dictionary comprehension. Comprehensions are pretty natural once you are into python but can be a bit arcane when you first start.

So, lets start with the iteration.
If we have a dict:
>>> a = {"a" : 1, "b" : 2, "c" : 3}
We can get tuples of the key:value pairs with items()
>>> list(a.items())
[('a', 1), ('c', 3), ('b', 2)]
So we can iterate through these tuples:
>>> for k,v in a.items():
...     print(k,v)
...
('a', 1)
('c', 3)
('b', 2)
>>>
So making the dict without the comprehension:
>>> b = {} # make an empty dict
>>> for k,v in a.items():
...     if v % 2: # is the value odd
...         b[k] = v # set key to value
...
>>> b
{'a': 1, 'c': 3}
And with the comprehension it is much more concise:
>>> c = {k:v for k,v in a.items() if v % 2}
>>> c
{'a': 1, 'c': 3}
Reply
#9
Is there a reason why creating dictionaires via enumerate would break the code at the end?

Trying to solve it via enumerate and I think I have the first 2 parts worked out but changing that broke the 3rd part.

import string
def dictfunc():
    letlist = dict(enumerate(string.ascii_lowercase))

dictfunc()

#Create dictionary for part 2
def dictfunc2():
    letstring = dict(enumerate(string.ascii_lowercase))

dictfunc2()

def odds_only():
    my_dict = dictfunc()
    return {k: v for k, v in my_dict.items() if k % 2}

print(odds_only())
Slowly absorbing all the information above about dictionaries. I don't understand why changing the way I go about creating the dictionary would break later code.
Reply
#10
The thing is dictfunc() function will not be very helpful because it does not return anything.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Looping to Create Nested Dictionary gngu2691 10 33,501 Jun-22-2018, 04:11 PM
Last Post: anickone

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020