Python 3 lists to dictionary - python

I have a three lists and I would like to build a dictionary using them:
a = [a,b,c]
b = [1,2,3]
c = [4,5,6]
i expect to have:
{'a':1,4, 'b':2,5, 'c':3,6}
All I can do now is:
{'a':1,'b':2, 'c':3}
What should i do?

You can try this:
a = ["a","b","c"]
b = [1,2,3]
c = [4,5,6]
new_dict = {i:[j, k] for i, j, k in zip(a, b, c)}
Output:
{'b': [2, 5], 'c': [3, 6], 'a': [1, 4]}
If you really want a sorted result, you can try this:
from collections import OrderedDict
d = OrderedDict()
for i, j, k in zip(a, b, c):
d[i] = [j, k]
Now, you have an OrderedDict object with the keys sorted alphabetically.

check this: how to zip two lists into new one
i suggest to first zip the b and c lists and then map them into a dictionary again using zip:
a = ['a','b','c']
b = [1,2,3]
c = [4,5,6]
vals = zip(b,c)
d = dict(zip(a,vals))
print(d)

a = ['a','b','c']
b = [1,2,3]
c = [4,5,6]
result = { k:v for k,*v in zip(a,b,c)}
RESULT
print(result)

Related

Python: vertical binning of two lists

I have two lists of the same size:
A = [1, 1, 2, 2, 3, 3, 4, 5]
B = [a, b, c, d, e, f, g, h] # numeric values
How do I do a vertical binning?
Output desired:
C = [ 1, 2, 3, 4, 5] # len = 5
D = [a + b, c + d, e + f, g, h] # len = 5
i.e. a mapping of A list to its cumulative sum (vertical binning?) where it occurs in list B.
I assume a, b, ... are numeric variables:
bins = dict()
for b, x in zip(A,B):
bins[b] = bins.setdefault(b, 0) + x
C = [key for key in bins]
D = [bins[key] for key in bins]
If a, b, ... are of another type, you would have to adjust the default value in bins.setdefault(b, ...).
This is a perfect case for the use of itertools.groupby:
from itertools import groupby
from operator import itemgetter
fst = itemgetter(0)
A = [1,1,2,2,3,3,4,5]
B = [1,3,4,6,7,7,8,8]
C = []
D = []
for k, v in groupby(zip(A, B), key=fst):
C.append(k)
D.append(sum(item[-1] for item in v))
C
>>[1, 2, 3, 4, 5]
D
>>[4, 10, 14, 8, 8]
If B is a list of strings then your summation operation becomes:
D.append(''.join(item[-1] for item in v))
You can use a dictionary and since Python 3.6 the order is preserved, therefore you get your C as the keys and D as values:
A = [1,1,2,2,3,3,4,5]
B = ["a","b","c","d","e","f","g","h"]
from random import randint
rename_to_B_for_numeric = [randint(0, 255) for _ in A]
result = {}
for idx, item in enumerate(A):
if item not in result:
# not sure about the type, so...
result[item] = "" if isinstance(B[idx], str) else 0
result[item] += B[idx]
print(result)
# {1: 'ab', 2: 'cd', 3: 'ef', 4: 'g', 5: 'h'}
print(list(result.keys()))
# [1, 2, 3, 4, 5]
print(list(result.values()))
# ['ab', 'cd', 'ef', 'g', 'h']
obviously if the type of item in B is not a string nor a number (int in this case) you'll need to modify the code a little bit to get some default type. Or just use else:
if item not in result:
result[item] = B[idx]
else:
result[item] += B[idx]
Here, C is the unique values of A:
C = sorted(set(A))
gives:
[1, 2, 3, 4, 5]
Now, D is the vertical binning of B w.r.t A (if B's elements are alpha):
D = [''.join(B[i] for i in range(len(B)) if A[i] == j) for j in C]
if B's elements are num:
D = [sum(B[i] for i in range(len(B)) if A[i] == j) for j in C]
gives:
['ab', 'cd', 'ef', 'g', 'h']
Note:
A = [1,1,2,2,3,3,4,5]
B = ['a','b','c','d','e','f','g','h']
Here a,b,c,... if numeric, go for the second eqn :)

How to specifically select item from a list with index information and assign them to library

I am working on a function to exclude all occurrences in a list and return a tuple/list with index information that will be assigned to a library. For example:
for a list input:
x = [0,0,1,2,3,0,0,]
output:
{"inds":[2,3,4],"vals":[1,2,3]}
My current solution is very ungly:
def function(x):
b = list()
c = list()
d = {'inds': [], 'vals': []}
a = list(enumerate(x))
for i in a:
if i[1]!=0:
b.append(i[1])
c.append(i[0])
d["inds"] = c
d["vals"] = b
return d
I am looking forward a concise solution.
You're basically there, you have the concept in mind. There's just a few ways to clean up your code.
There's no need to create lists b and c, when you can simply append the new data into the dictionary:
x = [0, 0, 1, 2, 3, 0, 0]
d = {'inds': [], 'vals': []}
for i, j in enumerate(x):
if j != 0:
d['inds'].append(i)
d['vals'].append(j)
print(d)
# Prints: {'vals': [1, 2, 3], 'inds': [2, 3, 4]}
There's also no need to call list() around enumerate(). I'm going to assume you use Python 3 here and that when you do enumerate(), you see something like:
<enumerate object at 0x102c579b0>
This is ok! This is because enumerate returns a special object of its own which is iterable just like a list, so you can simply loop through a. Also, since the list will have two values per item, you can do for i, j like I have.
idx, vals = zip(*[[n, v] for n, v in enumerate(x) if v])
d = {"inds": idx, "vals": vals}
>>> d
{'inds': [2, 3, 4], 'vals': [1, 2, 3]}
Your solution is ok, but you have some superfluous lines.
def function(x):
d = {'inds': [], 'vals': []}
for index, value in enumerate(x):
if value != 0:
d['inds'].append(index)
d['vals'].append(value)
return d
If performance is an issue for very long arrays you could also use numpy:
def function(x):
x_arr = np.array(x)
mask = x_arr != 0
indices = np.argwhere(mask)[:,0]
values = x_arr[mask]
return {'inds': list(indices), 'vals': list(values)}
You can do it also like this:
d = dict((i, v) for i, v in enumerate(x) if v)
d = {'inds': d.keys(), 'vals': d.values()}
EDIT:
If order matters, then like this (thanks to comments):
import collections
d = collections.OrderedDict((i, v) for i, v in enumerate(x) if v)
d = {'inds': d.keys(), 'vals': d.values()}
It can be done by this ugly functional one-liner:
{'inds': list(filter(lambda x: x>0, map(lambda (i,x): i if x>0 else 0 , enumerate(x)))), 'vals': list(filter(lambda x: x!=0, x))}
output:
{'inds': [2, 3, 4], 'vals': [1, 2, 3]}
this gives you inds:
list(filter(lambda x: x>0, map(lambda (i,x): i if x>0 else 0 , enumerate(x))))
this gives you values:
list(filter(lambda x: x!=0, x))

Return of a procedure using list in python

I am trying to add the value that is listed only in list y into list x.
I know I can use x.append(e) rather than x = x + [e] but I want to use +.
However, I don't know why I cannot produce the desired result, meaning that I cannot change the list a.
This is my code:
def union(x,y):
for e in y:
if e not in x:
x = x + [e]
a = [1,2,3]
b = [2,4,6]
union(a,b)
print a
print b
The result is:
a = [1,2,3], b = [2,4,6]
My expected result of print a is [1,2,3,4,6].
Just modify your union function to return the list x:
def union(x,y):
for e in y:
if e not in x:
x = x + [e]
return x
Then you can call:
>>> a = union(a,b)
>>> a
[1, 2, 3, 4, 6]
A shorter approach (with your same logic) would be using list comprehension:
>>> a += [i for i in b if i not in a]
>>> a
[1, 2, 3, 4, 6]
And the super-pythonic:
>>> list(set(a) | set(b))
[1, 2, 3, 4, 6]
It's worth pointing out that Python has the set data type for exactly this purpose. And it supports a .union(otherset) method!

Add integers to specific items in a list in python?

I would like to add some integer to a range of items in a list in python.
I know that this is correct if you want to add an integer to every item in a list:
A = 2
B = 5
C = 6
mylist = [1,2,3,4,5,6,7,8]
mylist[:] = [i+C for i in mylist]
print mylist
but I would like to add C to items A through B. so that instead of resulting in this list:
mylist = [7,8,9,10,11,12,13,14]
I would get this list:
mylist = [1,2,*9*,*10*,*11*,*12*,7,8]
is there a way to do this?
Thanks
Assign to a slice of the list:
>>> A = 2
>>> B = 5
>>> C = 6
>>> mylist = [1,2,3,4,5,6,7,8]
>>> mylist[A:B+1] = [i+C for i in mylist[A:B+1]]
>>> mylist
[1, 2, 9, 10, 11, 12, 7, 8]
>>>
for i in range(A, B+1):
mylist[i] += C
In addition to #iCodez answer, if you don't want to modify the original, you can use if-else
A = 2
B = 5
C = 6
oldlist = [1,2,3,4,5,6,7,8]
mylist = [x+C if A <= i <= B else x for i, x in enumerate(oldlist)]
mylist[A:B+1] = [i+C for i in mylist[A:B+1]]

convert n equal length lists to dictionary with unique keys from one list

I have n lists of equal length representing values of database rows. The data is pretty complicated, so i'll present simplified values in the example.
Essentially, I want to map the values of these lists (a,b,c) to a dictionary where the keys are the set of the list (id).
Example lists:
id = [1,1,1,2,2,2,3,3,3]
a = [1,2,3,4,5,6,7,8,9]
b = [10,11,12,13,14,15,16,17,18]
c = [20,21,22,23,24,25,26,27,28]
Needed dictionary output:
{id:[[a],[b],[c]],...}
{'1':[[1,2,3],[10,11,12],[20,21,22]],'2':[[4,5,6],[13,14,15],[23,24,25]],'3':[[7,8,9],[16,17,18],[26,27,28]]}
The dictionary now has a list of lists for the values in the original a,b,c subsetted by the unique values in the id list which is now the dictionary key.
I hope this is clear enough.
Try this:
id = ['1','1','1','2','2','2','3','3','3']
a = [1,2,3,4,5,6,7,8,9]
b = [10,11,12,13,14,15,16,17,18]
c = [20,21,22,23,24,25,26,27,28]
from collections import defaultdict
d = defaultdict(list)
# add as many lists as needed, here n == 3
lsts = [a, b, c]
for ki, kl in zip(id, zip(*lsts)):
d[ki] += [kl]
for k, v in d.items():
# if you don't mind using tuples, simply do this: d[k] = zip(*v)
d[k] = map(list, zip(*v))
The result is exactly as expected according to the question:
d == {'1':[[1,2,3],[10,11,12],[20,21,22]],
'2':[[4,5,6],[13,14,15],[23,24,25]],
'3':[[7,8,9],[16,17,18],[26,27,28]]}
=> True
IDs = [1,1,1,2,2,2,3,3,3]
a = [1,2,3,4,5,6,7,8,9]
b = [10,11,12,13,14,15,16,17,18]
c = [20,21,22,23,24,25,26,27,28]
import itertools
d = {}
for key, group in itertools.groupby(sorted(zip(IDs, a, b, c)), key=lambda x:x[0]):
d[key] = map(list, zip(*group)[1:]) # [1:] to get rid of the ID
print d
OUTPUT:
{1: [[1, 2, 3], [10, 11, 12], [20, 21, 22]],
2: [[4, 5, 6], [13, 14, 15], [23, 24, 25]],
3: [[7, 8, 9], [16, 17, 18], [26, 27, 28]]}

Categories