How can I enter a dictionary inside an another empty dictionary? - python-3.x

The example code -
innerdict = {}
outerdict = {}
for line in range(1, 10, 2):
for j in range(1, 10, 2):
line_tuple = ("Item" + str( line ), int( line ))
key = line_tuple[1]
if line ==j:
outerdict[key] = dict( innerdict )
outerdict[key] = {'Name': '{0}'.format( "item"+str(j) ), 'Price': '{0}'.format( j )}
print(outerdict)
The ouput comes out like this-
{1: {'Name': 'item1', 'Price': '1'}, 3: {'Name': 'item3', 'Price': '3'}, 5: {'Name': 'item5', 'Price': '5'}, 7: {'Name': 'item7', 'Price': '7'}, 9: {'Name': 'item9', 'Price': '9'}}
The above output is achievable since it is conventional. I found a lot of online suggestions regarding nested dictionary comprehension.
But I want the output to come out like below-
{{'Name': 'item1', 'Price': '1'}, {'Name': 'item3', 'Price': '3'}, {'Name': 'item5', 'Price': '5'}, {'Name': 'item7', 'Price': '7'}, {'Name': 'item9', 'Price': '9'}}
Thanks in advance!

This is not possible, as the dict objects are not hashable.
{{1:2}} would mean putting a dict {1:2} into a set, which is not possible because of the un-hashability of the objects mentioned above. Better put them in a list:
[{1:2}, {2:3}]

What you want is something like a list of dictionaries. And this {{'Name': 'item1', 'Price': '1'}, {'Name': 'item3', 'Price': '3'}, {'Name': 'item5', 'Price': '5'}, {'Name': 'item7', 'Price': '7'}, {'Name': 'item9', 'Price': '9'}} is invalid as dictionary is considered to be a key-value pair and there is no key in this.
It can be checked by assigning the above to a variable and then checking its type.
d = {{'Name': 'item1', 'Price': '1'}, {'Name': 'item3', 'Price': '3'}, {'Name': 'item5', 'Price': '5'}, {'Name': 'item7', 'Price': '7'}, {'Name': 'item9', 'Price': '9'}}
print(type(d))
It will result in an error saying it's unhashable.

Related

create nested object from records oriented dictionary

I have the following data frame:
[{'Name': 'foo', 'Description': 'foobar', 'Value': '5'}, {'Name': 'baz', 'Description': 'foobaz', 'Value': '4'}, {'Name': 'bar', 'Description': 'foofoo', 'Value': '8'}]
And I'd like to create two nested categories. One category for Name, Description keys and another category for Value key. Example of output for one object:
{'details': {'Name': 'foo', 'Description': 'foobar'}, 'stats': { 'Value': '5' }}
so far I'm only able to achieve this by joining "manually" each items. I'm pretty sure this is not the right solution.
Here is one solution:
data = [{'Name': 'foo', 'Description': 'foobar', 'Value': '5'}, {'Name': 'baz', 'Description': 'foobaz', 'Value': '4'}, {'Name': 'bar', 'Description': 'foofoo', 'Value': '8'}]
df = pd.DataFrame(data)
m = df.to_dict('records')
stats = [{'stats':i.popitem()} for i in m]
details = [{'details':i} for i in m]
g = list(zip(details,stats))
print(*g)
({'details': {'Name': 'foo', 'Description': 'foobar'}}, {'stats': ('Value', '5')}) ({'details': {'Name': 'baz', 'Description': 'foobaz'}}, {'stats': ('Value', '4')}) ({'details': {'Name': 'bar', 'Description': 'foofoo'}}, {'stats': ('Value', '8')})
The major function here is popitem(), which destructively pulls out a pair from the dictionary.
Using list comprehension:
from json import dump
result = [{
'details': {col: row[col] for col in ['Name', 'Description']},
'stat': {col: row[col] for col in ['Value']}
} for row in df.to_dict(orient='records')]
# Write to file
with open('result.json', 'w') as f:
dump(result, f)

Python list of dictionaries search with multiple input

Sorry for such a stupid question but im on deadend right now (1st time using python), how do i search Python list of dictionaries with multiple
attribute ?
My current code is only can search by 1 attribute.
people = [{'name': 'Alex', 'age': '19',
'grade': 80},
{'name': 'Brian', 'age': '17', 'grade':
90},
{'name': 'Junior', 'age': '17', 'grade':
90},
{'name': 'Zoey', 'age': '19', 'grade':
95},
{'name': 'joe', 'age': '18', 'grade':
90}]
entry=input("Check the name you want to search the grade :")
list(filter(lambda person: person['name'] == entry, people))
I want it to search by multitple attribute, so if i input either '17' or 90, the expected output is
[{'name': 'Brian', 'age': '17', 'grade': 90},
{'name': 'Junior', 'age': '17', 'grade': 90}]
You could just use two conditions connected by an or (while taking measures not to compare strings with numbers):
list(filter(lambda person: str(person['grade']) == entry or str(person['grade']) == entry, people))
At some point, a comprehension will be more readable:
[p for p in people if str(person['grade']) == entry or str(p['grade']) == entry]
And if you want to add more search keys, you can further DRY this out, using any:
keys = ('name', 'grade', 'age')
filtered = [p for p in people if any(str(p[k]) == entry for k in keys)]

Pick two items from a list based on a condition

Here is the simplified version of the problem ;)
Given following list,
my_list = [{'name': 'apple', 'type': 'fruit'},
{'name': 'orange', 'type': 'fruit'},
{'name': 'mango', 'type': 'fruit'},
{'name': 'tomato', 'type': 'vegetable'},
{'name': 'potato', 'type': 'vegetable'},
{'name': 'leek', 'type': 'vegetable'}]
How to pick only two items from the list for a particular type to achieve following?
filtered = [{'name': 'apple', 'type': 'fruit'},
{'name': 'orange', 'type': 'fruit'},
{'name': 'tomato', 'type': 'vegetable'},
{'name': 'leek', 'type': 'vegetable'}]
You can use itertools.groupby to group the elements of your list based on type and the grab only the first 2 elements from each group.
>>> from itertools import groupby
>>> f = lambda k: k['type']
>>> n = 2
>>> res = [grp for _,grps in groupby(sorted(my_list, key=f), f) for grp in list(grps)[:n]]
>>> pprint(res)
[{'name': 'apple', 'type': 'fruit'},
{'name': 'orange', 'type': 'fruit'},
{'name': 'tomato', 'type': 'vegetable'},
{'name': 'potato', 'type': 'vegetable'}]
you can groupby then pick the first 2:
from itertools import groupby
a = [list(j)[:2] for i, j in groupby(my_list, key = lambda x: x['type'])]
print(a)
[[{'name': 'apple', 'type': 'fruit'}, {'name': 'orange', 'type': 'fruit'}],
[{'name': 'tomato', 'type': 'vegetable'},
{'name': 'potato', 'type': 'vegetable'}]]
sum(a,[])
Out[299]:
[{'name': 'apple', 'type': 'fruit'},
{'name': 'orange', 'type': 'fruit'},
{'name': 'tomato', 'type': 'vegetable'},
{'name': 'potato', 'type': 'vegetable'}]

How to properly recombine grouped observables?

I'm trying to create a tool for analysing stock prices.
I've got a stream of price data for different stocks, and I want to have an observable to emit events whenever it receives a new, distinct and complete set of prices.
My plan: grouping the stream into different sub-streams for different stocks, and recombining their latest values.
Let's say I've got a stream of events like this:
from rx import Observable
stock_events = [
{'stock': 'A', 'price': 15},
{'stock': 'A', 'price': 16},
{'stock': 'B', 'price': 24},
{'stock': 'C', 'price': 37},
{'stock': 'A', 'price': 18},
{'stock': 'D', 'price': 42},
{'stock': 'B', 'price': 27},
{'stock': 'B', 'price': 27},
{'stock': 'C', 'price': 31},
{'stock': 'D', 'price': 44}
]
price_source = Observable.from_list(stock_events)
Here is my first (naive) approach:
a_source = price_source.filter(lambda x: x['stock'] == 'A').distinct_until_changed()
b_source = price_source.filter(lambda x: x['stock'] == 'B').distinct_until_changed()
c_source = price_source.filter(lambda x: x['stock'] == 'C').distinct_until_changed()
d_source = price_source.filter(lambda x: x['stock'] == 'D').distinct_until_changed()
(Observable
.combine_latest(a_source, b_source, c_source, d_source, lambda *x: x)
.subscribe(print))
This correctly gives me:
({'stock': 'A', 'price': 18}, {'stock': 'B', 'price': 24}, {'stock': 'C', 'price': 37}, {'stock': 'D', 'price': 42})
({'stock': 'A', 'price': 18}, {'stock': 'B', 'price': 27}, {'stock': 'C', 'price': 37}, {'stock': 'D', 'price': 42})
({'stock': 'A', 'price': 18}, {'stock': 'B', 'price': 27}, {'stock': 'C', 'price': 31}, {'stock': 'D', 'price': 42})
({'stock': 'A', 'price': 18}, {'stock': 'B', 'price': 27}, {'stock': 'C', 'price': 31}, {'stock': 'D', 'price': 44})
Yet, I feel that this should be better handled by group_by, instead of several filterings, so here's a re-write:
(price_source
.group_by(lambda e: e['stock'])
.map(lambda obs: obs.distinct_until_changed())
.combine_latest(lambda *x: x)
.subscribe(print))
But this time, I get:
(<rx.core.anonymousobservable.AnonymousObservable object at 0x000000000105EA20>,)
(<rx.core.anonymousobservable.AnonymousObservable object at 0x000000000776AB00>,)
(<rx.core.anonymousobservable.AnonymousObservable object at 0x000000000776A438>,)
(<rx.core.anonymousobservable.AnonymousObservable object at 0x000000000775E7F0>,)
What have I missed here? How do I "unwrap" the nested observables?
If you did want to use groupby it would be something like below in C#. This doesn't meet your requirement of a "complete" set though. As per comments, suspect CombineLatest would be better here.
price_source.GroupBy(x => x.Stock)
.Select(gp => gp.DistinctUntilChanged(x => x.Price))
.SelectMany(x => x)
.Subscribe(s => Console.WriteLine($"{s.Stock} : {s.Price}"));

Splitting tuple into segments

If I have the following tuple...:
("Year-7 [{'Name': 'Barry', 'Age': 11}, {'Name': 'Larry', 'Age': 11}]",
"Year-8 [{'Name': 'Harry', 'Age': 11}, {'Name': 'Parry', 'Age': 11}]",
"Year-9 [{'Name': 'Sally', 'Age': 11}, {'Name': 'Garry', 'Age': 11}]")
How do I split this up into the following tuples?
("Year-7", "Year-8, "Year-9")
("[{'Name': 'Barry', 'Age': 11}, {'Name': 'Larry', 'Age': 11}]", "[{'Name': 'Harry', 'Age': 11}, {'Name': 'Parry', 'Age': 11}]", "[{'Name': 'Sally', 'Age': 11}, {'Name': 'Garry', 'Age': 11}]")
Thanks in advance,
Jack
.................
t = ("Year-7 [{'Name': 'Barry', 'Age': 11}, {'Name': 'Larry', 'Age': 11}]",
"Year-8 [{'Name': 'Harry', 'Age': 11}, {'Name': 'Parry', 'Age': 11}]",
"Year-9 [{'Name': 'Sally', 'Age': 11}, {'Name': 'Garry', 'Age': 11}]")
tuple([k[7:] for k in list(t)])
Did you also want:
tuple([k[:6] for k in list(t)])

Resources