Problem when passing several lists in function with Python - python-3.x

here is my script :
time_remaining = [1, 2, 3, 4]
url_links = ["a", "b", "c"]
nb_bookies = ['5', '7', '6']
def gitanerie(time, url, book):
if len(time) != len(url):
url = url.append('d')
book = book.append('1')
else:
pass
return url, nb_bookies
url_links, nb_bookies = gitanerie(time_remaining, url_links, nb_bookies)
print(url_links)
print(nb_bookies)
When I run it it gives me :
None
['5', '7', '6', '1']
the url_kinks is empty. How to solve this problem. Thanks

Don't use in place url and book bacause append has no return type value rather follow this,
def gitanerie(time, url, book):
if len(time) != len(url):
url.append('d')
book.append('1')
else:
pass
return url, nb_bookies

You are returning the wrong variables in your function and instead of book = book.append('d') use book.append('d')
time_remaining = [1, 2, 3, 4]
url_links = ["a", "b", "c"]
nb_bookies = ['5', '7', '6']
def gitanerie(time, url, book):
if len(time) != len(url):
url.append('d')
book.append('1')
else:
pass
return url, book
url_links, nb_bookies = gitanerie(time_remaining, url_links, nb_bookies)
print(nb_bookies,url_links)
This will result in:
['5', '7', '6', '1'] ['a', 'b', 'c', 'd']

Related

combine two lists in a dictionary keep duplicate values of a key which has multi values

I want to combine two lists into a dictionary, but keep all values of each key. See my desired output:
Two lists:
a = ['E', 'AA', 'AA','AA', 'S', 'P']
b = ['11', '22', '33','44', '55', '66']
Output is a dictionary:
dict_1 = {'E': ['11'], 'AA': ['22', '33', '44'], 'S': ['55'], 'P': ['66']}
Problem:
I have the following code, after trying many times, I still only get an undesired output as follows
(I have tried a whole afternoon):
Current undesired output:
dict_1 = {'E': ['11'], 'AA': ['44'], 'S': ['55'], 'P': ['66']}
My code:
a = ['E', 'AA', 'AA','AA', 'S', 'P']
b = ['11', '22', '33','44', '55', '66']
c = []
dict_1 = {}
i = 0
while i < 6:
j = i
c = []
while i<= j <6:
if a[i]==a[j]:
c.append(b[j])
j+=1
dict_1[a[i]] = c
# print(dict_1)
i+=1
print(dict_1)
New to Python, nothing elegant on coding. I only want to update it so that I can get my desired output.
If anyone has a hint on it, please feel free to comment or answer. Thanks!
You can use dict.setdefault:
a = ["E", "AA", "AA", "AA", "S", "P"]
b = ["11", "22", "33", "44", "55", "66"]
dict_1 = {}
for i, j in zip(a, b):
dict_1.setdefault(i, []).append(j)
print(dict_1)
Prints:
{'E': ['11'], 'AA': ['22', '33', '44'], 'S': ['55'], 'P': ['66']}

Remove all keys excepts those mentioned from a dict python3

i have a nested python dictionary where i am trying to remove all keys except those mentioned. I found a solution here where we can remove keys specified, what i am trying to do is reverse of it, i want to remove all keys except those mentioned. So i made a slight change in the function, but i am getting an empty dict.
from collections import MutableMapping
def remove_fields(d, list_of_keys_to_remove):
if not isinstance(d, (dict, list)):
return d
if isinstance(d, list):
return [v for v in (remove_fields(v, list_of_keys_to_remove) for v in d) if v]
return {k: v for k, v in ((k, remove_fields(v, list_of_keys_to_remove)) for k, v in d.items()) if
k in list_of_keys_to_remove}
Adding sample input
EDIT: let suppose i want to keep RENEWAL_TYPE
{
'G_1': [
{
'ACCOUNTING_RULE_ID': '1',
'PAYMENT_TERM_ID': '4',
'RENEWAL_TYPE': 'RENEW'
},
{
'ACCOUNTING_RULE_ID': '2',
'PAYMENT_TERM_ID': '4',
'RENEWAL_TYPE': 'RENEW'
},
{
'ACCOUNTING_RULE_ID': '3',
'PAYMENT_TERM_ID': '4',
'RENEWAL_TYPE': 'DO_NOT_RENEW'
},
{
'ACCOUNTING_RULE_ID': '4',
'PAYMENT_TERM_ID': '4',
'RENEWAL_TYPE': 'RENEW'
}
]
}
You're looking for the intersection between the set of keys in the dict and the set of values in the list. i.e. all keys that exist in both sets.
Try this:
from collections import MutableMapping
d = { 'A': 1, 'B': 2, 'C': 3, 'D': 4 }
list_of_keys_to_keep = ['B', 'C', 'F']
def remove_fields(d, list_of_keys_to_keep):
return {key: value for key, value in d.items() if key in list_of_keys_to_keep}
print(remove_fields(d, list_of_keys_to_keep)) # -> {'B': 2, 'C': 3}
Edit: Updated name of list_of_keys_to_remove to list_of_keys_to_keep since this seems to be what it actually represents.
Edit2: Updated after Askers update. The following works for the sample provided:
from collections import MutableMapping
d = {
'G_1': [
{
'ACCOUNTING_RULE_ID': '1',
'PAYMENT_TERM_ID': '4',
'RENEWAL_TYPE': 'RENEW'
},
{
'ACCOUNTING_RULE_ID': '2',
'PAYMENT_TERM_ID': '4',
'RENEWAL_TYPE': 'RENEW'
},
{
'ACCOUNTING_RULE_ID': '3',
'PAYMENT_TERM_ID': '4',
'RENEWAL_TYPE': 'DO_NOT_RENEW'
},
{
'ACCOUNTING_RULE_ID': '4',
'PAYMENT_TERM_ID': '4',
'RENEWAL_TYPE': 'RENEW'
}
]
}
list_of_keys_to_keep = ['RENEWAL_TYPE']
def filter_dict(di, keys):
if not isinstance(di, (dict, list)):
return di
if isinstance(di, list):
return [filter_dict(value, keys) for value in di]
return {key: filter_dict(value, keys) for key, value in di.items() if key in keys or isinstance(value, (dict, list))}
print(filter_dict(d, list_of_keys_to_keep))
Output:
{'G_1': [{'RENEWAL_TYPE': 'RENEW'}, {'RENEWAL_TYPE': 'RENEW'}, {'RENEWAL_TYPE': 'DO_NOT_RENEW'}, {'RENEWAL_TYPE': 'RENEW'}]}
try this one:
dict = {"a": 1, "b": 2, "c": 3, "d": 4, "e": 5}
keys_to_preserve = ["e", "b", "c"]
dict_final={k: v for k,v in dict.items() if k in keys_to_preserve}
def remove_fields(d, keys_to_preserve):
if isinstance(d, list):
return [remove_fields(v, keys_to_preserve) for v in d]
elif isinstance(d, dict):
return dict([(k, remove_fields(v, keys_to_preserve)) for k, v in d.items() if k in keys_to_preserve])
else:
return d

Making dictionary from 2 lists

I have following two lists:
list1 = ['17-Q2', '1.00', '17-Q3', '2.00', '17-Q4', '5.00', '18-Q1', '6.00']
list2 = ['17-Q2', '1', '17-Q3', '2', '17-Q4', '5', '18-Q1', '6']
I want a dictionary in the following way. Can I do that in Python?
result = [17-Q2: 1(1.00), 17-Q3: 2(2.00), 17-Q4: 5(5.00), 18-Q1: 6(6.00)]
Here's one approach to this:
result = {}
list1=['17-Q2', '1.00', '17-Q3', '2.00', '17-Q4', '5.00', '18-Q1', '6.00']
list2=['17-Q2', '1', '17-Q3', '2', '17-Q4', '5', '18-Q1', '6']
for i in range(0, len(list1)-1, 2):
result[list1[i]] = list2[i + 1] + '(' + list1[i+1] + ')' ;
You can zip the two lists and then zip the resulting iterable with itself so that you can iterate through it in pairs to construct the desired dict:
i = zip(list1, list2)
result = {k: '%s(%s)' % (v2, v1) for (k, _), (v1, v2) in zip(i, i)}
result becomes:
{'17-Q2': '1(1.00)', '17-Q3': '2(2.00)', '17-Q4': '5(5.00)', '18-Q1': '6(6.00)'}
You can use zip and dict.
keys = ["a", "b", "c", "d"]
values = ["A", "B", "C"]
print(dict(zip(keys, values)))
# prints: {'a': 'A', 'b': 'B', 'c': 'C'}
This works because dict can take a list (or any iterator) of tuples of (key, value) to be created. The zip function allows to build tuples from lists:
zip returns an iterator of tuples, where the i-th tuple contains the i-th element from each of the argument sequences or iterables.
Notice that this will only return a dictionary that pairs the shortest list (either keys or value) with the corresponding element.
If you wish to have a default value for unpaired elements you can always use itertools.zip_longest
from itertools import zip_longest
keys = ["a", "b", "c", "d"]
values = ["A", "B", "C"]
print(dict(zip_longest(keys, values)))
# prints: {'a': 'A', 'b': 'B', 'c': 'C', 'd': None}
You can also use zip_longest keyword parameter fillvalue to have something else than None when the corresponding value isn't found.
On the other hand, if you have more values than keys, this wouldn't make much sense as you would erase the default key (namely fillvalue) for every missing element.
Assuming your input to be as follows:
list1 = ['17-Q2', '1.00', '17-Q3', '2.00', '17-Q4', '5.00', '18-Q1', '6.00']
list2 = ['17-Q2', '1', '17-Q3', '2', '17-Q4', '5', '18-Q1', '6']
And Desired Output to be as follows:
result = {17-Q2: 1(1.00), 17-Q3: 2(2.00), 17-Q4: 5(5.00), 18-Q1: 6(6.00)}
Following code with a single while loop could help:
from collections import OrderedDict
final_dict = dict()
i = 0 # Initializing the counter
while (i<len(list1)):
# Updating the final dict
final_dict.update({list1[i]:str(list2[i+1]) + "(" + str(list1[i+1]) + ")"})
i += 2 # Incrementing by two in order to land on the alternative index
# If u want sorted dictionary
sorted_dict = OrderedDict(sorted(final_dict.items()))
print (sorted_dict)

How to make my program faster

"""
ID: nihaowa2
LANG: PYTHON3
TASK: namenum
"""
import time
start=time.time()
translate = {2: ("A","B","C"), 5: ("J","K","L"), 8: ("T","U","V"), 3:("D","E","F"), 6: ("M","N","O"), 9: ("W","X","Y"), 4: ("G","H","I") ,7 ("P","R","S")}
names=[""]
def newlist(nl,num):
nnl=[]
for i in translate[num]:
for j in nl:
nnl.append(j+i)
return nnl
gnd=open ('dict.txt', 'r')
goodnames=[]
for i in range(4616):
goodnames.append(gnd.readline()[:-1])
goodnames.append(gnd.readline())
fin = open ('namenum.in', 'r')
fout = open ('namenum.out', 'w')
namenumber=(fin.readline().split()[0])
for i in namenumber:
names=newlist(names,int(i))
ok=[]
for i in names:
if i in goodnames:
ok.append(i)
if ok==[]:
fout.write("NONE\n")
else:
ok.sort()
for i in ok:
fout.write(i+"\n")
fout.close()
The code above is my attempt to solve this problem . But the grader says it is too slow . I need it to run under 1 second . Could anyone please give me some suggestions?
It is faster if you read in the whole file, prepare a dictionary from {"Number" : [list of names]} - For simplicity I choose to keep the string input and make a string out of the key for the dict as {str:[str,...], ...}
You can then simply look up the cows number in the dict wich is O(1):
mapping = {'A': '2', 'B': '2', 'C': '2',
'D': '3', 'E': '3', 'F': '3',
'G': '4', 'H': '4', 'I': '4',
'J': '5', 'K': '5', 'L': '5',
'M': '6', 'N': '6', 'O': '6',
'P': '7', 'R': '7', 'S': '7',
'T': '8', 'U': '8', 'V': '8',
'W': '9', 'X': '9', 'Y': '9',
'Q': '', 'Z': '' # part of names in the file, not mapped to a number
}
# read file, one word per list entry, cleaned
def readDict(fn="dict.txt"):
with open(fn) as f:
all = f.readlines()
return [x.strip('\n').strip() for x in all]
# a name as number
def getNameAsNum(name):
return ''.join( mapping[c] for c in name)
# dict of numbers as key and all names as list
def namesAsNums():
names = readDict()
d={}
for name in names:
asNum = getNameAsNum(name)
if asNum and name:
d.setdefault(asNum[:], list())
d[asNum].append(name[:])
d[asNum].sort()
return d
# get the mapping of number to list of names
nan = namesAsNums()
# get input and ---
cow = input("Which cow serial number?")
# limit string to 12
cow = ''.join(cow[0:12])
# ... check and print
if cow in nan:
for n in nan[cow]:
print(n)
else:
print ("NONE")
Parsing the file takes my laptop 0.16s - lookup of it in the dict is negligable.
If there were many names with same numbers in the file I would forgoe the sort on every dict-insert and use a second go over the whole dict to sort the list when all names are in it - but for this file its the same runtime.

Referencing a number inside a tuple

I want to arrange a list of tuples similar to the one bellow in descending order using the numbers:
data = [('ralph picked', ['nose', '4', 'apple', '30', 'winner', '3']),
('aaron popped', ['soda', '1', 'popcorn', '6', 'pill', '4',
'question', '29'])]
I would like to sort the nested list so that the outcome would look somewhat like:
data2 = [('ralph picked', ['apple', '30', 'nose', '4', 'winner', '3']),
('aaron popped', ['question', '29', 'popcorn', '6', 'pill', '4', 'soda', '1'])]
I am trying to use this code for this:
data2=[]
for k, v in data:
data2 = ((k, sorted(zip(data[::2], data[1::2]), key=lambda x: int(x[1]), reverse=True) ))
[value for pair in data2 for value in pair]
print(data2)
But I keep getting the error message:
TypeError: int() argument must be a string or a number, not 'tuple'
I tried to rearrange the int in key=lambda x: int(x[1]) to different things, but I kept getting the same message, I am very new to python, the syntax often gets me. Any ideas on how to solve this? I really thank you very much!
Rather than trying to do everything at once, let's give things names:
data = [('ralph picked', ['nose', '4', 'apple', '30', 'winner', '3']),
('aaron popped', ['soda', '1', 'popcorn', '6', 'pill', '4', 'question', '29'])]
data2 = []
for k, v in data:
new_list = sorted(zip(v[::2], v[1::2]), key=lambda x: int(x[1]), reverse=True)
flattened = [value for pair in new_list for value in pair]
new_tuple = (k, flattened)
data2.append(new_tuple)
produces
>>> print(data2)
[('ralph picked', ['apple', '30', 'nose', '4', 'winner', '3']),
('aaron popped', ['question', '29', 'popcorn', '6', 'pill', '4', 'soda', '1'])]
You need to distinguish between data and v -- you only want to sort v, and you need to store the result of the list comprehension, otherwise you're just building it and throwing it away.
When you're having trouble with the syntax, break everything apart into its pieces and print them to see what's going on. For example, you could decompose new_list into
words = v[::2]
numbers = v[1::2]
pairs = zip(words, numbers)
sorted_pairs = sorted(pairs, key=lambda x: int(x[1]), reverse=True)
and sorted_pairs is really what new_list is.

Resources