Create arrays of arrays and use dictionary - python

I have two lists:
x = ['1','5','X','9']
y = ['X','9','9P']
which I have combined like this:
z = [x,y]
print(z)
So, "z" is a list of two lists and it looks like this:
[['1', '5', 'X', '9'], ['X', '9', '9P']]
I have this dictionary:
delqType = {
'1' : 0,
'2' : 3,
'3' : 4,
'4' : 5,
'5' : 6,
'7' : 19,
'8' : 21,
'8A' : 20,
'8P' : 16,
'9' : 22,
'9B' : 18,
'9P' : 15,
'UR' : 23,
'X' : -99999
}
I want to apply the dictionary delqType to the list "z" in order to get this new list (called "t") that looks like:
[[0, 6, -99999, 22], [-99999, 22, 15]]
I have tried this code:
t = []
for i in range(len(z)):
for j in range(len(z[i])):
t.append(delqType[z[i][j]])
next
But I get one list (and not a list of two lists as I want):
[0, 6, -99999, 22, -99999, 22, 15]
How can I get a list of two lists containing the elements after they have been transformed using the dictionary?

You can use nested list comprehension.
t = [[delqType[i] for i in list_i] for list_i in z]
print(t)
[[0, 6, -99999, 22], [-99999, 22, 15]]

You should created the nested lists in t, one for each nested list of z. In addition it will be simpler to iterate the items instead of the indices:
t = []
for sub in z:
t.append([])
for item in sub:
t[-1].append(delqType[item])
Another nice way is to use the itemgetter operator to map the list of keys to the list of values:
from operator import itemgetter
t = [itemgetter(*sub)(delqType) for sub in z]

As you want to get a 2 dimensions list, you need to append a list inside your first for loop.
(But also, please use the for loop to directly extract values, instead of using indices !)
So, this would look like:
t = []
for sublist in z:
new_sublist = []
for key in sublist:
newlist.append(...)
t.append(new_sublist)
I let to you to fill the internals of the deepest for loop, as an exercise, to ensure you got it correctly :-)
Side note: your code sample is not correct, as there is no next keyword in Python!! Please be sure to provide the exact code you executed.

Related

Transforming a dict to another structure in Python

I have a dict like below:
{'activity_count': [10, 11, 12], 'type': ['all', 'paper', 'fpy']}
I want to transform this dict into this form:
{'all': {'activity_count': 10}, 'paper': {'activity_count': 11}, 'fpy': {'activity_count': 12}}
How can I solve this?
So far I tried this solution,
dic={"activity_count":[10,11,12],"type":["all","paper","fpy"]}
in={}
i=0
for val in dic['type']:
for v in dic['activity_count']:
if i== dic['activity_count'].index(v):
temp={}
temp['activity_count']=v
fin[val]=temp
i+=1
It works as I expected, but it looks very ineffective way to achieve this task. Is there a way to solve this problem?
Here a try, here zip is used to get values from both lists and to assign each:
d = {'activity_count': [10, 11, 12], 'type': ['all', 'paper', 'fpy']}
nd = {j:{'activity_count':i} for i, j in zip(d['activity_count'], d['type'])}
print(nd)
I would go for zip and dict comprehension:
test = {'activity_count': [10, 11, 12], 'type': ['all', 'paper', 'fpy']}
solution = {key:{'activity_count':value} for value, key in zip(test["activity_count"],test["type"])}
Explanation: The zip of your two list groups the elements of the two list by with identical index. So it will convert your lists to a generator where the values are like this: [(10, 'all'), (11, 'paper'), (12, 'fpy')]. But the generator is lazy evaluated, so the tuples are only processed, when the dict comprehension asks for them, this saves memory.
The dict comprehension just iterates over this generator and puts the second element as key and the first one as value.
You could try this dictionary comprehension using enumerate:
dictionary = {'activity_count': [10, 11, 12], 'type': ['all', 'paper', 'fpy']}
{e:{"activity_count":dictionary.get("activity_count")[c]} for c,e in enumerate(dictionary.get("type"))}

What is the quickest way to map between lists in python

I have pairs of 4 lists a and b with integer values such as list_1a = [1,2,3,...] and list_1b = [8,11,15,...]. The idea is that the integer values in list_1a are now represented by the integer values in list_1b, and the same for list_2a and list_2b etc.
Now I have a list of 4 columns final_list which contained integer values corresponding to the a lists. I want to map the values in final_list to the values in the b lists. What is the quickest way to do this in python ?
Is there a quicker way than using lists ?
Edit:
To clarify the question, take the following example:
list_1a = [1,2,3]
list_1b = [8,11,15]
list_2a = [5,6,7,8]
list_2b = [22,26,30,34]
list_3a = [11,12,13,14,18]
list_3b = [18,12,25,28,30]
list_4a = [51,61,72,82]
list_4b = [73,76,72,94]
Note that some of these lists can contain more than a million entries (So maybe memory can be an issue)
The lists do not have the same length
All of the integer values in these lists are unique to their lists, i.e. list_1a + list_1b will never have a repeating integer value.
final_list should look like final_list_b after the mapping occurs
final_list_a = [[1,6,11,51],[3,6,14,72]]
final_list_b = [[8,26,18,73],[15,26,28,72]]
To put things into perspective, this questions is for a database application where these "lists" contain auto-generated key values
I think what you want is a dictionary, which associates keys with values. Unless i'm confused about what you want to do here.
So if I make 4 short example lists.
list_1a = [1,2,3,4]
list_1b = [8,11,15,18]
list_2a = [5,6,7,8]
list_2b = [22,26,30,34]
and make them into a big list of all "a" values and all "b" values.
a_list = list_1a + list_2a
b_list = list_1b + list_2b
I can then use zip to merge the lists into a dictionary
my_dict = dict(zip(a_list, b_list))
print(my_dict)
See:
how to merge 2 list as a key value pair in python
for some other ways to do this last bit.
result:
{1: 8, 2: 11, 3: 15, 4: 18, 5: 22, 6: 26, 7: 30, 8: 34}
Now your "a" list makes up the keys of this dictionary.. while the "b" list make up the values. You can access the values by using the keys. here's some examples.
print(my_dict.keys())
print(my_dict.values())
print(my_dict[5])
gives me:
[1, 2, 3, 4, 5, 6, 7, 8]
[8, 11, 15, 18, 22, 26, 30, 34]
22
Is this what you want?
EDIT: I feel that I should note that while my dictionary has printed in order, dictionaries are actually not ordered like lists. You might want to look into collections.OrderedDict or sorted if this is important to you.
Update:
For what you want to do, maybe consider nested dictionaries. You can make a dictionary whose values are dictionaries, also note that when 1a and 1b don't match in length, zip doesn't care and just excludes 60:
list_1a = [1,2,3,4]
list_1b = [8,11,15,18,60]
list_2a = [5,6,7,8]
list_2b = [22,26,30,34]
a_dict = dict(zip(list_1a, list_2a))
b_dict = dict(zip(list_1b, list_2b))
my_dict = {"a" : a_dict, "b" : b_dict}
print(my_dict)
Result:
{'a': {1: 5, 2: 6, 3: 7, 4: 8}, 'b': {8: 22, 18: 34, 11: 26, 15: 30}}
Now you can access the inner values in a different way:
print(my_dict["a"].keys())
print(my_dict["a"].values())
print(my_dict["a"][4])
Result:
[1, 2, 3, 4]
[5, 6, 7, 8]
8

Unpack a List in to Indices of another list in python

Is it possible to unpack a list of numbers in to list indices? For example I have a lists with in a list containing numbers like this:
a = [[25,26,1,2,23], [15,16,11,12,10]]
I need to place them in a pattern so i did something like this
newA = []
for lst in a:
new_nums = [lst[4],lst[2],lst[3],lst[0],lst[1]]
newA.append(new_nums)
print (newA) # prints -->[[23, 1, 2, 25, 26], [10, 11, 12, 15, 16]]
so instead of writing new_nums = [lst[4],lst[2],lst[3],lst[0],lst[1]] , i thought of defining a pattern as list called pattern = [4,2,3,0,1] and then unpack these in to those indices of lst to create new order of lst.
Is there a fine way to do this.
Given a list of indices called pattern, you can use a list comprehension like so:
new_lst = [[lst[i] for i in pattern] for lst in a]
operator.itemgetter provides a useful mapping function:
from operator import itemgetter
a = [[25,26,1,2,23], [15,16,11,12,10]]
f = itemgetter(4,2,3,0,1)
print [f(x) for x in a]
[(23, 1, 2, 25, 26), (10, 11, 12, 15, 16)]
Use list(f(x)) if you want list-of-lists instead of list-of-tuples.
If you're not opposed to using numpy, then try something like:
import numpy as np
pattern = [4, 2, 3, 0, 1]
newA = [list(np.array(lst)[pattern]) for lst in a]
Hope it helps.
In pure Python, you can use a list comprehension:
pattern = [4,2,3,0,1]
newA = []
for lst in a:
new_nums = [lst[i] for i in pattern]
newA.append(new_nums)
In numpy, you may use the fancy indexing feature:
>>> [np.array(lst)[pattern].tolist() for lst in a]
[[23, 1, 2, 25, 26], [10, 11, 12, 15, 16]]
it is slower than other, but it is another option. you can sort the list based on your pattern
a = [[25,26,1,2,23], [15,16,11,12,10]]
pattern = [4,2,3,0,1]
[sorted(line,key=lambda x:pattern.index(line.index(x))) for line in a]
[[23, 1, 2, 25, 26], [10, 11, 12, 15, 16]]

How to apply a dict in python to a string as opposed to a single letter

I am trying to output the alphabetical values of a user entered string, I have created a dict and this process works, but only with one letter.
If I try entering more than one letter, it returns a KeyError: (string I entered)
If I try creating a list of the string so it becomes ['e', 'x', 'a', 'm', 'p', 'l', 'e'] and I get a TypeError: unhashable type: 'list'
I cannot use the chr and ord functions (I know how to but they aren't applicable in this situation) and I have tried using the map function once I've turned it to a list but only got strange results.
I've also tried turning the list into a tuple but that produces the same error.
Here is my code:
import string
step = 1
values = dict()
for index, letter in enumerate(string.ascii_lowercase):
values[letter] = index + 1
keyw=input("Enter your keyword for encryption")
keylist=list(keyw)
print(values[keylist])
Alt version without the list:
import string
step=1
values=dict()
for index, letter in enumerate(string.ascii_lowercase):
values[letter] = index + 1
keyw=input("Enter your keyword for encryption")
print(values[keyw])
You need to loop through all the letters and map each one individually:
mapped = [values[letter] for letter in keyw]
print(mapped)
This uses a list comprehension to build the list of integers:
>>> [values[letter] for letter in 'example']
[5, 24, 1, 13, 16, 12, 5]
The map() function would do the same thing, essentially, but returns an iterator; you need to loop over that object to see the results:
>>> for result in map(values.get, 'example'):
... print(result)
5
24
1
13
16
12
5
Note that you can build your values dictionary in one line; enumerate() takes a second argument, the start value (which defaults to 0); using a dict comprehension to reverse the value-key tuple would give you:
values = {letter: index for index, letter in enumerate(string.ascii_lowercase, 1)}
You most certanly can use ord()
inp = input('enter stuff:')
# a list of the ord() value of alphabetic character
# made uppercase and subtracted 64 --> position in the alphabet
alpha_value = [ord(n.upper())-64 for n in inp if n.isalpha()]
print(alpha_value)
Test:
import string
print([ord(n.upper())-64 for n in string.ascii_lowercase if n.isalpha()])
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]
You can write simple for loop to map alphabet to integer.
try to this.
print[(item, (values[item]))for item in keylist]

Pythonic way for max-sum-max multiple lists

I have 3 lists:
a1 = range(10)
a2 = range(10,20)
a3 = range(20,30)
I need to do the following:
For each list, get max of every 5 element blocks, so hypothetically:
a1_maxes = [max1_a1, max2_a1]
a2_maxes = [max1_a2, max2_a2]
a3_maxes = [max1_a3, max2_a3]
Sum each "maxes" list, so:
for each i:
sum_i = sum(ai_maxes)
Take the max of these 3 sums, so:
max(sum_1, sum_2, sum_3)
I could not get myself to use map() here. What would be the most Pythonic (concise) way to do this? Thanks.
a1 = range(10)
a2 = range(10,20)
a3 = range(20,30)
print(max(sum(x[i:i+5]) for x in (a1,a2,a3) for i in xrange(0,len(a1),5)))
135
Just get the sumof each chunk x[i:i+5]
To make it more obvious, the lists become split into the following chucks:
print(list(x[i:i+5]) for x in [a1,a2,a3] for i in xrange(0,len(a1),5))
[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12, 13, 14], [15, 16, 17, 18, 19], [20, 21, 22, 23, 24], [25, 26, 27, 28, 29]]
Then max just gets the largest sum:
If you want the highest two elements from each check:
mx_pair = max(sorted(x[i:i+5])[-2:] for x in (a1,a2,a3) for i in xrange(0,len(a1),5))
print(sum(mx_pair))
57
If the answer should be 53:
from itertools import izip,imap
def chunks(l):
for i in xrange(0,len(l), 5):
yield l[i:i+5]
sums = (max(izip(*ele)) for ele in imap(chunks,(a1,a2,a3)))
print(sum(max(sums)))
Let's break this into pieces.
The first point is that you probably don't want separate a1, a2, and a3` variables; if you're going to have to do the exact same thing repeatedly to multiple values, and then iterate over those values, they probably belong in a list. So:
a = [a1, a2, a3]
Now, how do you split an iterable into 5-element pieces? There are a number of ways to do it, from the grouper function in the itertools recipes to zipping slices to iterating over slices. I'll use grouper:
grouped = [grouper(sublist, 5) for sublist in a]
Now we just want the max value of each group, so:
maxes = [[max(group) for group in sublist] for sublist in a]
And now, we want to sum up each sublist:
sums = [sum(sublist) for sublist in maxes]
And finally, we want to take the max of these sums:
maxsum = max(sums)
Now, given that each of these list comprehensions is only being used as a one-shot iterable, we might as well turn them into generator expressions. And if you want to, you can merge some of the steps together:
maxsum = max(sum(max(group) for group in grouper(sublist, 5)) for sublist in a)
And, having done that, you don't actually need a to be created explicitly, because it only appears once:
maxsum = max(sum(max(group) for group in grouper(sublist, 5))
for sublist in a1, a2, a3)

Categories