why does dictionnary only print the last 3 items? [duplicate] - python

This question already has answers here:
How can one make a dictionary with duplicate keys in Python?
(9 answers)
Closed 6 years ago.
d ={"A":"h","K":"h","Q":"h","A":"c","K":"c","Q":"c","A":"d","K":"d","Q":"d","A":"s","K":"s","Q":"s"}
print(d)
When I do this, it prints out:
{'A': 's', 'Q': 's', 'K': 's'}
How do I get to print out everything? I have trouble finding out how to write a dictionary with the same values on different keys.

As others have mentioned in the comments, you cannot have duplicate key's in a dictionary, Python knows to update the existing key with the latest value it's been set to in the duplicate declarations.
You could have a Dictionary that has a tuple (immutable), or list (mutable) as its value.
So if you wanted to have the following coupled information:
'Ah', 'As', 'Ac', 'Ad' , 'Kh', 'Ks' ...
You could represent that data with:
d = { 'A' : ('h', 's', 'c', 'd'), 'K' : ('h', 's') }
A list value can also work if you wanted to mutate the data within the list. (or set if you do not want duplicate values)
d = { 'A' : ['h', 's', 'c', 'd'], 'K' : ['h', 's'] }
This way you have essentially factored out your common character to be your key.

You could have some other list data structure like this:
my_list = [["A", ["h", "c", "d", "s"]], ["K", ["h", "c", "d", "s"]], ["Q", ["h", "c", "d", "s"]]]
and maybe even convert it into a more usable dictionary, like this:
dic = {}
for item in my_list:
key = item[0]
value = item[1]
dic[key] = value
print(dic)
Output:
{'Q': ['h', 'c', 'd', 's'], 'K': ['h', 'c', 'd', 's'], 'A': ['h', 'c', 'd', 's']}

Related

How to use recursion in heterogenous list and dict

I was learning about recursion in python and solved some common problems like factorial, iterating through nested lists etc.
While solving such problems, I came up with this challenge where you have to use recusion to traverse through a heterogeneous input(an input which contains single str elements, nested lists, dictionary etc).
So the challenge involves traversing through all the values in this input and replace a specified value with another one.
The input used here looks like this:
input = ['a', 'b', {'1':{'o':'a'}}, 'c', 'd', {'T': 'b', 'K': [1, 'a', 3, {'S':{'Z':'t'},'R':{'3':'a'}}, {'key':[66,'a',88]}, ['a', 'c']]}, ['a'], 3, 'r', 'a']
The input is a list which itself contains lists and dicts, and some of these lists and dicts are nested and also have one another in themselves.
And the output that I'm expecting to get is:
# this is the output that should be got at the end, after running the code
['#', 'b', {'1':{'o':'#'}}, 'c', 'd', {'T': 'b', 'K': [1, '#', 3, {'S':{'Z':'t'},'R':{'3':'#'}}, {'key':[66,'#',88]}, ['#', 'c']]}, ['#'], 3, 'r', '#']
# exactly like input but with all 'a' replaced with '#'
# of course we can use treat change the input to string and then use replace() of string module and get the output
# but then this wont be a challenge would it?
correct = ['a', 'b', 'a', 'c', 'd', 'b', 1, 'a', 3, 't', 'a', 66, 'a', 88, 'a', 'c', 'a', 3, 'r', 'a']
The code I wrote is:
remove = 'a'
replace = 'X'
output = []
def recall(input):
for item in input:
if isinstance(item, list):
recall(item)
elif isinstance(item, dict):
for entry in item.values():
recall(entry)
else:
if isinstance(input, dict) and item in input.keys():
if input[item]==remove:
input[item]=replace
output.append(input[item])
else:
output.append(input[item])
else:
if item==remove:
item=replace
output.append(item)
else:
output.append(item)
print(item)
recall(input)
print(output)
This produces the output:
['X', 'b', 'X', 'c', 'd', 'b', 1, 'X', 3, 't', 'X', 66, 'X', 88, 'X', 'c', 'X', 3, 'r', 'X']
# a single list with all the 'a' replaced but there are no dicts with their key value pairs in it
I havn't been able to find a way to achieve the desired output.
Am I doing something wrong? Or is there any way the desired output can be achieved with recursion?
You are appending all the values to a single global output variable regardless of whether they are from a nested dict or list. Instead, you need to get the function to return a value so that the function at the next level up can deal with it appropriately - appending a dict or list in the right position in the nested hierarchy. For example, you could do it this way:
def replace_values(item, replacement):
if isinstance(item, list):
return [replace_values(v, replacement) for v in item]
elif isinstance(item, dict):
return {k: replace_values(v, replacement) for k, v in item.items()}
# Alternatively, in case you need the dict keys to be replaced too:
# return {replacement.get(k, k): replace_values(v, replacement) for k, v in item.items()}
else:
return replacement.get(item, item)
input_list = ['a', 'b', {'1':{'o':'a'}}, 'c', 'd', {'T': 'b', 'K': [1, 'a', 3, {'S':{'Z':'t'},'R':{'3':'a'}}, {'key':[66,'a',88]}, ['a', 'c']]}, ['a'], 3, 'r', 'a']
print(replace_values(input_list, {"a": "#"}))
Note that the type (dict, list, or other) and ordering of the elements are the same in the return value as in the input item. This preserves the nested structure of the input.

How to use sort() for set() values in Python?

Basic code:
var1 = ['b', 'a', 'c', 'd']
var2 = ['c', 'a']
print(set(var1).difference(set(var2)))
Output:
{'b', 'd'}
Question
Is it possible to sort this output into alphabetical order? If so, how can I?
This is what I have tried:
print(set(var1).difference(set(var2)).sort())
But error shows up:
print(set(var1).difference(set(var2)).sort())
AttributeError: 'set' object has no attribute 'sort'
Sets have no order, so sorting them makes no sense. But if you pass a set to sorted it will be turned into a list and sorted:
print(sorted(set(var1).difference(set(var2))))
Here is the code that will solve the problem:
var1 = ['b', 'a', 'c', 'd']
var2 = ['c', 'a']
print(sorted(set((set(var1).difference(set(var2))))))
Output:
['b', 'd']
You might be wondering that the output is a list and not a set. That's because the whole point of using a set, both in mathematics as a tool and in programming languages as a data structure is that it's not ordered. Meaning the sets {p, q} and {q, p} are the same set!
You can get the list of elements in your set sorted alphabetically by comparing the ord of the different characters.
test_list = ["a", "b", "u", "x", "e", "f", "k", "z"]
test_set = set(test_list)
sorted_list = sorted(test_set, key=ord) # == ['a', 'b', 'e', 'f', 'k', 'u', 'x', 'z']

Get level of items in a nested list

Problem:
I have some linked data and I want to build a structure like this one on this picture :
and get the level of each item because in the future I will make some calculations by staring at the lowest level of my tree structure.
Expected Result:
I need to get a structure that gives me items per level :
level 0: A
level 1: A = B, C,D
level 2: D = E, F, G
level 3: E = H,I , J, K
what I have tried so far:
I've tried this recursive code to simulate the behavior but I'm unable to get items the level of items.
dict_item = {"A": ["B","C","D"], "D": ["E","F","G"], "E":["H","I","J"]}
def build_bom(product):
if not dict_item.get(product):
return product
else :
return [build_bom(x) for x in dict_item.get(product)]
print(build_bom("A"))
My output is a nested list like this :
['B', 'C', [['H', 'I', 'J'], 'F', 'G']]
My Question:
I'm not sure if this is the best approach to handle my problem.
And how to get the desired output?
here is the desired output :
[ {"parent_E":["H", "I", "J"]},
{"parent_D": ["E", "F", "G"]},
{"parent_A"} :["D","C","B"]},
]
A list of dictionaries ( where keys are parents and values are children), the first element in the list is the lowest level of my structure and the last is the highest element.
PS: This is a simulation but in future, I will have to works on large datasets with this code.
Any Help will be appreciated
This is how I will approach this problem. First, I'll generate the tree from your dict_item object.
dict_item = {"A": ["B","C","D"], "D": ["E","F","G"], "E":["H","I","J"]}
def build_tree(x):
if x in dict_item:
return {x: [build_tree(v) for v in dict_item[x]]}
else:
return x
tree = build_tree("A")
print(tree)
>>> {'A': ['B', 'C', {'D': [{'E': ['H', 'I', 'J']}, 'F', 'G']}]}
Then, do a breadth-first search on the tree. Each time we hit an element that has children, we append it to a list:
results = []
queue = [tree]
while queue:
x = queue.pop(0)
if isinstance(x, dict):
parent, children = list(x.items())[0]
results.append({'parent_' + parent: dict_item[parent]})
for child in children:
queue.append(child)
print(results)
>>> [{'parent_A': ['B', 'C', 'D']}, {'parent_D': ['E', 'F', 'G']}, {'parent_E': ['H', 'I', 'J']}]
Then all we need to do now, is to reverse the list:
print list(reversed(results))
>>> [{'parent_E': ['H', 'I', 'J']}, {'parent_D': ['E', 'F', 'G']}, {'parent_A': ['B', 'C', 'D']}]

Retrieving single dictionary element in Python [duplicate]

This question already has answers here:
In what order does python display dictionary keys? [duplicate]
(4 answers)
Closed 8 years ago.
I want to retrieve only the fourth item in the dictionary "e" (below).
I tried using the OrderedDict() method, but it didn't work. Here are my results:
from collections import OrderedDict
e = OrderedDict()
e = {'a': 'A',
'b': 'B',
'c': 'C',
'd': 'D',
'e': 'E'
}
for k, v in e.items():
print k, v
print e.items()[3]
The last line returns: ('e', 'E')
So I turned the keys and values into lists, but here's how the lists appeared when I printed them:
['a', 'c', 'b', 'e', 'd']
['A', 'C', 'B', 'E', 'D']
For me, this explained why it happened, but not how it happened.
So, next I sorted them. That gave me the results I was looking for -- but it seemed unnecessarily complicated:
e = {'a': 'A',
'b': 'B',
'c': 'C',
'd': 'D',
'e': 'E'
}
k, v = sorted(e.keys()), sorted(e.values())
print "{}: {}".format(k[3], v[3])
Result:
d: D
OrderedDict() wasn't necessary.
Is there an easier way to do this? And can someone explain why the elements in the dictionary are ordered like this:
keys: 'a', 'c', 'b', 'e', 'd'
values: 'A', 'C', 'B', 'E', 'D'
... which defies the structure of my original dictionary?
You're not using an ordered dict.
e = OrderedDict()
e = {'a': 'A',
'b': 'B',
'c': 'C',
'd': 'D',
'e': 'E'
}
The first line creates an OrderedDict. The second line throws it away and replaces it with a regular dict, which is unordered. (Python variables don't have types.)
But you can't just do this:
e = OrderedDict({'a': 'A', ...})
...because that's still a regular dict, which is still unordered, and OrderedDict can't magically recreate your original source ordering.
Try this:
e = OrderedDict([('a', 'A'), ('b', 'B'), ...])
Now you should have a dict-like object with the ordering you want.
And can someone explain why the elements in the dictionary are ordered like this ... which defies the structure of my original dictionary?
Because dictionaries are unordered. They're just hash maps, and hash maps have no inherent ordering.
Note that you could also do this, which will preserve the pairing of keys and values (whereas your separate sortings will not):
print sorted(e.items())[3]

Change the way sorted works in Python (different than alphanumeric)

I'm representing cards in poker as letters (lower and uppercase) in order to store them efficiently. I basically now need a custom sorting function to allow calculations with them.
What is the fastest way to sort letters in Python using
['a', 'n', 'A', 'N', 'b', 'o', ....., 'Z']
as the ranks rather than
['A', 'B', 'C', 'D', 'E', 'F', ....., 'z']
which is the default?
Note, this sorting is derived from:
import string
c = string.letters[:13]
d = string.letters[13:26]
h = string.letters[26:39]
s = string.letters[39:]
'a' = 2 of clubs
'n' = 2 of diamonds
'A' = 2 of hearts
'N' = 2 of spades
etc
You can provide a key function to sorted, this function will be called for each element in the iterable and the return value will be used for the sorting instead of the elements value.
In this case it might look something like the following:
order = ['a', 'n', 'A', 'N', 'b', 'o', ....., 'Z']
sorted_list = sorted(some_list, key=order.index)
Here is a brief example to illustrate this:
>>> order = ['a', 'n', 'A', 'N']
>>> sorted(['A', 'n', 'N', 'a'], key=order.index)
['a', 'n', 'A', 'N']
Note that to make this more efficient you may want to use a dictionary lookup for your key function instead of order.index, for example:
order = ['a', 'n', 'A', 'N', 'b', 'o', ....., 'Z']
order_dict = {x: i for i, x in enumerate(order)}
sorted_list = sorted(some_list, key=order_dict.get)
Store [edit: not store, use internally] them as numbers ordered by value and only convert to letters when displaying them.
Edit: if 1 byte values are required then you can have the cards in the range 1:52 as characters, then, again, convert to the proper letters when displaying and storing them.

Categories

Resources