dictionary with nested list values to single list of values - python-3.x

I am trying to make single list of values in dictionary for each key. Bellow is problem. I am trying to parse list in Jinja and looks better to convert them into one before taking to template.
Problem:
{'EFTPOS': [[10.0, 5.0], 15.0], 'StoreDeposit': [[5.0, 6.0], 11.0]}
Result:
{'EFTPOS': [10.0, 5.0, 15.0], 'StoreDeposit': [5.0, 6.0, 11.0]}

Please try this code snippet.I have defined a method to remove the nested list and convert it into a flat list.
output = []
def rmNest(ls):
for i in ls:
if type(i) == list:
rmNest(i)
else:
output.append(i)
return output
a_dict = {'EFTPOS': [[10.0, 5.0], 15.0], 'StoreDeposit': [[5.0, 6.0], 11.0]}
new_dict = {}
for i in a_dict:
new_dict[i] = rmNest(a_dict[i])
output = []

Related

How to know the quantity of different items in a list

I have a list of names (I, not Schindler, nor Arya), say:
names_list = ['Oscar', 'Itzhak', 'Amon', 'Ilyn', 'Melisandre', 'Cersei', 'Oscar', 'Cersei', 'who red this and didn't answer' ]
Also I have a list with some coordinates in my imaginary world, lets say:
coords = [[1.1, 2.2, 3.3], [1.1, 2.2, 3.3], [2.9, 2.9, 3.3], [5.0, 1.0, 3.0]]
And I have a function, which I'll call tears_counter, so when I pass my list as my function param, it returns the quantity of different elements my list holds. So, in this case:
tears_counter(names_list)
>>> 7
and
tears_counter(coords)
>>> 3
Hope you have understood, len() isn't the solution. Thanks in advance
We will add our list's elements to the set and because of set stores unique elements, set's length will give us unique element count of our list.
But there is a problem. Set store values via hashing and because of lists are mutable and doesn't have hash so i need to convert it to a tuple (tuples are immutable!).
from collections.abc import Iterable
def tuplify(value):
if isinstance(value, list):
return tuple(tuplify(x) for x in value)
else:
return value
def find_unique_count(data):
data = tuplify(data) # convert mutable objects to immutable objects.
unique = set()
for item in data:
unique.add(item)
return len(unique)
So, tuplify will convert multi nested lists to multi nested tuples (if any) and find_unique_count will add them to set. Finally set's length will give you our list's unique element count.
Examples and outputs:
coords = [[1.1, 2.2, 3.3], [1.1, 2.2, 3.3], [2.9, 2.9, 3.3], [5.0, 1.0, 3.0]]
names_list = ['Oscar', 'Itzhak', 'Amon', 'Ilyn','Melisandre', 'Cersei', 'Oscar', 'Cersei']
data = [[[1.1], 2.2, 3.3], [[1.1], 2.2, 3], "this", [2, [[5]]], 141, 5, 3, "that"]
print(find_unique_count(coords)) # 3 , because 0th and 1th elements are same!
print(find_unique_count(names_list)) # 6
print(find_unique_count(data)) # 7

Effective ways to group things into list

I am doing a K-means project and I have to do it by hand, which is why I am trying to figure out what is the best ways to group things according to their last values into a list or a dictionary. Here is what I am talking about
list_of_tuples = [(honey,1),(bee,2),(tree,5),(flower,2),(computer,5),(key,1)]
Now my ultimate goal is to be able to sort out the list and have 3 different lists each with its respected element
"""This is the goal"""
list_1 = [honey,key]
list_2 = [bee,flower]
list_3 = [tree, computer]
I can use a lot of if statements and a for loop, but is there a more efficient way to do it?
If you're not opposed to using something like pandas, you could do something along these lines:
import pandas as pd
list_1, list_2, list_3 = pd.DataFrame(list_of_tuples).groupby(1)[0].apply(list).values
Result:
In [19]: list_1
Out[19]: ['honey', 'key']
In [20]: list_2
Out[20]: ['bee', 'flower']
In [21]: list_3
Out[21]: ['tree', 'computer']
Explanation:
pd.DataFrame(list_of_tuples).groupby(1) groups your list of tuples by the value at index 1, then you extract the values as lists of index 0 with [0].apply(list).values. This gives you an array of lists as below:
array([list(['honey', 'key']), list(['bee', 'flower']),
list(['tree', 'computer'])], dtype=object)
Something to the effect can be achieved with a dictionary and a for loop, using the second element of the tuple as a key value.
list_of_tuples = [("honey",1),("bee",2),("tree",5),("flower",2),("computer",5),("key",1)]
dict_list = {}
for t in list_of_tuples:
# create key and a single element list if key doesn't exist yet
# append to existing list otherwise
if t[1] not in dict_list.keys():
dict_list[t[1]] = [t[0]]
else:
dict_list[t[1]].append( t[0] )
list_1, list_2, list_3 = dict_list.values()

Dictionary is not being added to

I'm trying to create a dictionary using keys and values from other dictionaries. The issue I'm having is that the dictionary I want to return comes up empty.
Note:
USER_RATING_DICT_SMALL = {1: {68735: 3.5, 302156: 4.0}, 2: {68735: 1.0, 124057: 1.5, 293660: 4.5}}
MOVIE_USER_DICT_SMALL = {293660: [2], 68735: [1, 2], 302156: [1], 124057: [2]}
def movies_to_users(user_ratings):
"""Return a dictionary of movie ids to list of users who rated the movie,
using information from the user_ratings dictionary of users to movie
ratings dictionaries.
>>> result = movies_to_users(USER_RATING_DICT_SMALL)
>>> result == MOVIE_USER_DICT_SMALL
True
"""
user_list = []
movie_to_users = {}
for items in user_ratings.items():
user_id = items[0]
user_list.append(user_id)
for items in user_ratings.items():
movie_id = items[1]
if movie_id in user_list:
movie_to_users[movie_id] = [user_list]
return movie_to_users
I created an empty dictionary for all the values and keys to accumulate to but it is not accumulating; it returns an empty dictionary instead. I want the output to be == MOVIE_USER_DICT_SMALL
A pretty short solution might be
MOVIE_USER_DICT_SMALL = {}
for user, data in USER_RATING_DICT_SMALL.items():
for movie in data.keys():
if not movie in MOVIE_USER_DICT_SMALL.keys():
# add entry for each movie
# will be an empty list if no user rated.
MOVIE_USER_DICT_SMALL[movie] = []
# for user in current iteration, there MUST be a rating...
# otherwise, movie would not be in data.keys()
MOVIE_USER_DICT_SMALL[movie] += [user]
MOVIE_USER_DICT_SMALL
# {68735: [1, 2], 302156: [1], 124057: [2], 293660: [2]}
The trick is to use key and value as returned by dict.items()

How do you create a new dictionary from a list, using positions to dictate keys and values?

I am trying to determine the most used active users in certain packages. I have a list with the packages and users as the elements. I would like to turn these into dictionary with the package name as the key and the username as the value. The pattern of the list is :
list = ['package1', 'userA', 'userB', 'package2', 'userC',
'userD', 'package3', 'userE', 'userF', ...]
I would like:
dict = {'package1': ['userA', 'userB'],
'package2': ['userC', 'userD'],
'package3': ['userE', 'userF'],
...}
I would like to be able to match the package by name and not by position. I currently have something like:
dict={}
for x in list:
if "package" in x:
dict.fromkeys(list, x)
Thanks for your help.
This is one approach using a simple iteration.
Ex:
lst = ['package1', 'userA', 'userB', 'package2', 'userC', 'userD', 'package3', 'userE', 'userF']
result = []
for i in lst:
if i.startswith("package"):
result.append([i])
else:
result[-1].append(i)
result = {i: v for i, *v in result}
print(result)
Output:
{'package1': ['userA', 'userB'],
'package2': ['userC', 'userD'],
'package3': ['userE', 'userF']}
Check out this code;
In [1]: raw_data = ['package1', 'userA', 'userB', 'package2', 'userC', 'userD',
...: 'package3', 'userE', 'userF']
In [2]: data = {}
In [3]: for el in raw_data:
...: if el.startswith('package'):
...: lastkey = el
...: data[el] = []
...: else:
...: data[lastkey].append(el)
...:
In [4]: data
Out[4]:
{'package1': ['userA', 'userB'],
'package2': ['userC', 'userD'],
'package3': ['userE', 'userF']}
If you can rely upon there always being exactly two users, then you ca easily use a dictionary comprehension with indexing and slicing to produce the keys and value-lists that you need:
output = {lst[i]: lst[i+1:i+3] for i in range(0, len(lst), 3)}
If the number of users might be variable though, you'll need a full loop. You need to remember the most recent package you've seen, and put each subsequent user into its associated list:
output = {}
current_package = unpackaged_users = []
for item in lst:
if item.startswith('package'):
current_package = []
output[item] = current_package
else: # or elif item.startswith('user')?
current_package.append(item)
The unpackaged_users variable will contain a list of any users that were included in the input before the first package was seen. If that can't happen in your code, you could probably do away with that variable (and if you don't initialize current_package before the loop, you'll get an exception if that situation ever comes up).

Python for loop with ifs

What I have:
I have two keys in a dictionary:
one with values and
one with the index of the value.
d = {}
d['inds'] = [0, 5, 4, 2, 2, 5, 1]
d['vals'] = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]
What I want to do:
I want to loop through the dictionary and:
If the next iteration index = the last iteration index +1, to list the corresponding value
If the next iteration index does not = the last iteration index +1, print 0 and keep going. so basically just filling in 0 when there is a missing index
What I have tried
If I use the below loop:
for i in d['inds']:
for v in d['vals']:
for x in range(0, i):
if i == x+1:
print(v)
break
else:
print(0)
I get the list of values 6 times.
So I tried swapping i and x:
for i in d['inds']:
for v in d['vals']:
for x in range(0, i):
if x == i+1:
print(v)
break
else:
print(0)
Now I just get 0 listed 7 times.
TL;DR
How do I loop through a dictionary's values and indexes with a conditional statement, what am I doing wrong?
If I understand correctly, you want something like this:
for i in range(len(d['inds'])):
if i in d['inds']:
print(d['vals'][i])
else:
print(0)
This iterates through all the possible indices, prints 0 if the current index is not in d['inds'], and prints the value at the current index if it is.
This solution requires functions chain and defaultdict:
from itertools import chain
from collections import defaultdict
Create a new dictionary of lists:
G = defaultdict(list)
Populate it with the data from d:
for k,v in zip(d['inds'], d['vals']):
G[k].append(v)
#{0: [1.0], 5: [2.0, 6.0], 4: [3.0], 2: [4.0, 5.0], 1: [7.0]}
Create a range of indexes:
indexes = range(min(d['inds']), max(d['inds']) + 1)
Lookup each index in the new dictionary. If an index is not in the dictionary, use [0] as the value. The result is a nested list that can be flattened with chain:
list(chain.from_iterable(G.get(x, [0]) for x in indexes))
#[1.0, 7.0, 4.0, 5.0, 0, 3.0, 2.0, 6.0]

Resources