How to iterate through dict in random order in Python? - python

How can I iterate through all items of a dictionary in a random order? I mean something random.shuffle, but for a dictionary.

A dict is an unordered set of key-value pairs. When you iterate a dict, it is effectively random. But to explicitly randomize the sequence of key-value pairs, you need to work with a different object that is ordered, like a list. dict.items(), dict.keys(), and dict.values() each return lists, which can be shuffled.
items=d.items() # List of tuples
random.shuffle(items)
for key, value in items:
print key, value
keys=d.keys() # List of keys
random.shuffle(keys)
for key in keys:
print key, d[key]
Or, if you don't care about the keys:
values=d.values() # List of values
random.shuffle(values) # Shuffles in-place
for value in values:
print value
You can also "sort by random":
for key, value in sorted(d.items(), key=lambda x: random.random()):
print key, value

You can't. Get the list of keys with .keys(), shuffle them, then iterate through the list while indexing the original dict.
Or use .items(), and shuffle and iterate that.

import random
def main():
CORRECT = 0
capitals = {'Alabama': 'Montgomery', 'Alaska': 'Juneau',
'Arizona': 'Phoenix', 'Arkansas': 'Little Rock'} #etc... you get the idea of a dictionary
allstates = list(capitals.keys()) #creates a variable name and list of the dictionary items
random.shuffle(allstates) #shuffles the variable
for a in allstates: #searches the variable name for parameter
studentinput = input('What is the capital of '+a+'? ')
if studentinput.upper() == capitals[a].upper():
CORRECT += 1
main()

I wanted a quick way for stepping through a shuffled list, so I wrote a generator:
def shuffled(lis):
for index in random.sample(range(len(lis)), len(lis)):
yield lis[index]
Now I can step through my dictionary d like so:
for item in shuffled(list(d.values())):
print(item)
or if you want to skip creating a new function, here is a 2-liner:
for item in random.sample(list(d.values()), len(d)):
print(item)

As Charles Brunet have already said that the dictionary is random arrangement of key value pairs. But to make it really random you will be using random module.
I have written a function which will shuffle all the keys and so while you are iterating through it you will be iterating randomly. You can understand more clearly by seeing the code:
def shuffle(q):
"""
This function is for shuffling
the dictionary elements.
"""
selected_keys = []
i = 0
while i < len(q):
current_selection = random.choice(q.keys())
if current_selection not in selected_keys:
selected_keys.append(current_selection)
i = i+1
return selected_keys
Now when you call the function just pass the parameter(the name of the dictionary you want to shuffle) and you will get a list of keys which are shuffled. Finally you can create a loop for the length of the list and use name_of_dictionary[key] to get the value.

Related

How to get a subset from an OrderedDict?

I have an OrderedDict in Python, and I only want to get the first key-vale pairs. How to get it? For example, to get the first 4 elements, i did the following:
subdict = {}
for index, pair in enumerate(my_ordered_dict.items()):
if index < 4:
subdict[pair[0]] = pair[1]
Is this the good way to do it?
That approach involves running over the whole dictionary even though you only need the first four elements, checking the index over and over, and manually unpacking the pairs, and manually performing index checking unnecessarily.
Making it short-circuit is easy:
subdict = {}
for index, pair in enumerate(my_ordered_dict.items()):
if index >= 4:
break # Ends the loop without iterating all of my_ordered_dict
subdict[pair[0]] = pair[1]
and you can nested the unpacking to get nicer names:
subdict = {}
# Inner parentheses mandatory for nested unpacking
for index, (key, val) in enumerate(my_ordered_dict.items()):
if index >= 4:
break # Ends the loop
subdict[key] = value
but you can improve on that with itertools.islice to remove the manual index checking:
from itertools import islice # At top of file
subdict = {}
# islice lazily produces the first four pairs then stops for you
for key, val in islice(my_ordered_dict.items(), 4):
subdict[key] = value
at which point you can actually one-line the whole thing (because now you have an iterable of exactly the four pairs you want, and the dict constructor accepts an iterable of pairs):
subdict = dict(islice(my_ordered_dict.items(), 4))
You can use a map function, like this
item = dict(map(lambda x: (x, subdict[x]),[*subdict][:4]))
Here is one approach:
sub_dict = dict(pair for i, pair in zip(range(4), my_ordered_dict.items()))
The length of zip(a,b) is equal to the length of the shortest of a and b, so if my_ordered_dict.items() is longer than 4, zip(range(4), my_ordered_dict.items() just takes the first 4 items. These key-value pairs are passed to the dict builtin to make a new dict.

How to use list extend() with map function on a dictionary

I am new to python and trying to understand how map function works
I have an input dictionary with key as a string and value as list of strings
input_dict = {'Mobile': ['Redmi', 'Samsung', 'Realme'],
'Laptop': ['Dell', 'HP'],
'TV': ['Videocon', 'Sony'] }
I want to convert it into a list like below
['Mobile_Redmi', 'Mobile_Samsung', 'Mobile_Realme', 'Laptop_Dell', 'Laptop_HP', 'TV_Videocon', 'TV_Sony']
so I tried using map function with list extend method like below.
def mapStrings(item):
key, value_list = item[0], item[1]
result = []
for val in value_list:
result.append(key+"_"+val)
return result
result_list = []
result_list.extend(map(mapStrings, input_dict.items()))
print(result_list)
The above code gives me
[['Mobile_Redmi', 'Mobile_Samsung', 'Mobile_Realme'], ['Laptop_Dell', 'Laptop_HP'], ['TV_Videocon', 'TV_Sony']]
I am trying to understand why the result_list.extend() did not produce the desired output.
extend adds all elements of an iterable to the list. In this case the elements are lists themselves, so you get a nested list. What you want is to extend the list with each list from the dict individually, something like:
result_list = []
for item in input_dict.items():
result_list.extend(mapStrings(item))
If you really want to use map, you can use:
result_list = [item for items in map(mapStrings, input_dict.items()) for item in items]
For more ways look at How to make a flat list out of list of lists? Just note that you are not really dealing with a list of lists, but with a map object so be careful for slight differences.

How to compare a value with a list of dicts without using for loop in python?

Input:
value = "apple"
dict = [{'name':'apple','color':"red"},{'name':'orange','color':"orange"}]
Witout using the for loop like below, is it possible to compare and get the values?
Code I have done:
for i in dict:
if i["name"] == value:
print i
You do have multiple dicts in a list, not just one.
Therefore you must go through all items in your list.
for d in dict: # dict is actually a list, but I am using your var name
if value in d.values():
print(value)

Parse a list, check if it has elements from another list and print out these elements

I have a list populated from entries of a log; for sake of simplicity, something like
listlog = ["entry1:abcde", "entry2:abbds", "entry1:eorieo", "entry3:orieqor", "entry2:iroewiow"......]
This list can have an undefined number of entry, which may or may not be in sequence, since I run multiple operations in async fashion.
Then I have another list, which I use as reference to get only the list of entries; which may be like
list_template = ["entry1", "entry2", "entry3"]
I am trying to use the second list, to get sequences of entries, so I can isolate the single sequence, taking only the first instance found of each entry.
Since I am not dealing with numbers, I can't use set, so I did try with a loop inside a loop, comparing values in each list
This does not work, because it is possible that another entry may happen before what I am looking for (say, I want entry1, entry2, entry3, and the loop find entry1, but then find entry3, and since I compare every element of each list, it will be happy to find an element)
for item in listlog:
entry, value = item.split(":")
for reference_entry in list_template:
if entry == reference_entry:
print item
break
I have to, in a nutshell, find a sequence as in the template list, while these items are not necessarily in order. I am trying to parse the list once, otherwise I could do a very expensive multi-pass for each element of the template list, until I find the first occurrence and bail out. I thought that doing the loop in the loop is more efficient, since my reference list is always smaller than the log list, which is usually few elements.
How would you approach this problem, in the most efficient and pythonic way? All that I can think of, is multiple passes on the log list
you can use dict:
>>> listlog
['entry1:abcde', 'entry2:abbds', 'entry1:eorieo', 'entry3:orieqor', 'entry2:iroewiow']
>>> list_template
['entry1', 'entry2', 'entry3']
>>> for x in listlog:
... key, value = x.split(":")
... if key not in my_dict and key in list_template:
... my_dict[key] = value
...
>>> my_dict
{'entry2': 'abbds', 'entry3': 'orieqor', 'entry1': 'abcde'}
Disclaimer : This answer could use someone's insight on performance. Sure, list/dict comprehensions and zip are pythonic but the following may very well be a poor use of those tools.
You could use zip :
>>> data = ["a:12", "b:32", "c:54"]
>>> ref = ['c', 'b']
>>> matches = zip(ref, [val for key,val in [item.split(':') for item in data] if key in ref])
>>> for k, v in matches:
>>> print("{}:{}".format(k, v))
c:32
b:54
Here's another (worse? I'm not sure, performance-wise) way to get around this :
>>> data = ["a:12", "b:32", "c:54"]
>>> data_dict = {x:y for x,y in [item.split(':') for item in data]}
>>> ["{}:{}".format(key, val) for key,val in md.items() if key in ref]
['b:32', 'c:54']
Explanation :
Convert your initial list into a dict using a dict
For each pair of (key, val) found in the dict, join both in a string if the key is found in the 'ref' list
You can use a list comprehension something like this:
import re
listlog = ["entry1:abcde", "entry2:abbds", "entry1:eorieo", "entry3:orieqor", "entry2:iroewiow"]
print([item for item in listlog if re.search('entry', item)])
# ['entry1:abcde', 'entry2:abbds', 'entry1:eorieo', 'entry3:orieqor', 'entry2:iroewiow']
Than u can split 'em as u wish and create a dictonary if u want:
import re
listlog = ["entry1:abcde", "entry2:abbds", "entry1:eorieo", "entry3:orieqor", "entry2:iroewiow"]
mylist = [item for item in listlog if re.search('entry', item)]
def create_dict(string, dict_splitter=':'):
_dict = {}
temp = string.split(dict_splitter)
key = temp[0]
value = temp[1]
_dict[key] = value
return _dict
mydictionary = {}
for x in mylist:
x = str(x)
mydictionary.update(create_dict(x))
for k, v in mydictionary.items():
print(k, v)
# entry1 eorieo
# entry2 iroewiow
# entry3 orieqor
As you see this method need an update, cause we have changing the dictionary value. That's bad. Most better to update value for the same key. But it's much easier as u can think

How to access specific element of dictionary of tuples

I want to access a specific element of a tuple in a dictionary of tuples. Let's say that I have a dictionary with a unique key, and a tuple with three values, for each key. I want to write a iterator the prints every third item in a tuple for every element in the dictionary.
For example
dict = {"abc":(1,2,3), "bcd":(2,3,4), "cde", (3,4,5)}
for item in dict:
print item[2]
But this returns
c
d
e
Where am I going wrong?
for item in dict:
print dict[item][2]
Also, you should not name anything after a built-in, so name your dictionary 'd' or something other than 'dict'
for item in dict: does the same thing as for item in dict.keys().
Alternatively, you can do:
for item in dict.values():
print item[2]
Your code is close, but you must key into the dictionary and THEN print the value in index 2.
You are printing parts of the Keys. You want to print parts of the Values associated with those Keys:
for item in dict:
print dict[item][2]

Categories