Is a dictionary within a dictionary with any list values - python-3.x

I have a question regarding dictionaries and how to tell if a dictionary appears in another. In the example below, I wish to check if d1 appears in d2 which as shown below:
d1 = { 'a': '1', 'b': '2', 'c': '3' }
d2 = { 'a': '1', 'b': '2', 'c': '3', 'd': '4', 'e': '5' }
res = all(item in d2.items() for item in d1.items())
However, I have a case where I wish to be able to pass in a list of values and check that the values for a, b and any of the values of c appear in d2.
d1 = { 'a': '1', 'b': '2', 'c': ['3', '33', '333'] }
d2 = { 'a': '1', 'b': '2', 'c': '3', 'd': '4', 'e': '5' }
Any help would be appreciated.

If I understand correctly, in your 2nd example, the result should be True since '3' belongs to list d1['c'] and d2['c'] == 3. If I am right then this might work:
d1 = { 'a': '1', 'b': '2', 'c': ['3', '33', '333'] }
d2 = { 'a': '1', 'b': '2', 'c': '3', 'd': '4', 'e': '5' }
res = all(item in d2.items() if not isinstance(item[1], list)
else any((item[0], x) in d2.items() for x in item[1])
for item in d1.items())
print(res)

Related

How to compare particular element in list python3?

l1= [['1', 'apple', '1', '2', '1', '0', '0', '0'], ['1',
'cherry', '1', '1', '1', '0', '0', '0']]
l2 = [['1', 'cherry', '2', '1'],
['1', 'plums', '2', '15'],
['1', 'orange', '2', '15'],
['1', 'cherry', '2', '1'],
['1', 'cherry', '2', '1']]
output = []
for i in l1:
for j in l2:
if i[1] != j[1]:
output.append(j)
break
print(output)
Expected Output:
[['1', 'plums', '2', '15'], ['1', 'orange', '2', '15']]
How to stop iteration and find unique elements and get the sublist?
How to stop iteration and find unique elements and get the sublist?
To find the elements in L2 that are not in L1 based on the fruit name:
l1= [[1,'apple',3],[1,'cherry',4]]
l2 = [[1,'apple',3],[1,'plums',4],[1,'orange',3],[1,'apple',4]]
output = []
for e in l2:
if not e[1] in [f[1] for f in l1]: # search by matching fruit
output.append(e)
print(output)
Output
[[1, 'plums', 4], [1, 'orange', 3]]
You can store all the unique elements from list1 in a new list, then check for list2 if that element exists in the new list. Something like:
newlist = []
for item in l1:
if item[1] not in newlist:
newlist.append(item)
output = []
for item in l2:
if item[1] not in newlist:
output.append(item)
print(output)
This is slightly inefficient but really straightforward to understand.

Remove some same-index elements from two lists based on one of them

Let's suppose that I have these two lists:
a = [{'id': 3}, {'id': 7}, None, {'id': 1}, {'id': 6}, None]
b = ['5', '5', '3', '5', '3', '5']
I want to filter both at the same-index based though only on a and specifically on filtering out the None elements of a.
So finally I want to have this:
[{'id': 3}, {'id': 7}, {'id': 1}, {'id': 6}]
['5', '5', '5', '3']
I have written this code for this:
a_temp = []
b_temp = []
for index, el in enumerate(a):
if el:
a_temp.append(a[index])
b_temp.append(b[index])
a = a_temp[:]
b = b_temp[:]
I am wondering though if there is any more pythonic way to do this?
This solution
uses zip() to group corresponding elements of a and b together
Makes a list of 2-tuples of corresponding elements, such that the corresponding element of a is not None
Use the zip(*iterable) idiom to flip the dimensions of the list, thus separating the single list of 2-tuples into two lists of singletons, which we assign to new_a and new_b
a = [{'id': 3}, {'id': 7}, None, {'id': 1}, {'id': 6}, None]
b = ['5', '5', '3', '5', '3', '5']
new_a, new_b = zip(*((x, y) for x, y in zip(a, b) if x))
# new_a = ({'id': 3}, {'id': 7}, {'id': 1}, {'id': 6})
# new_b = ('5', '5', '5', '3')
If you just want a simple solution, please try:
a = [{'id': 3}, {'id': 7}, None, {'id': 1}, {'id': 6}, None]
b = ['5', '5', '3', '5', '3', '5']
n = []
for i in range(len(b)):
if a[i] is None:
n.append(i)
for i in sorted(n, reverse=True):
a.pop(i)
b.pop(i)
a
[{'id': 3}, {'id': 7}, {'id': 1}, {'id': 6}]
b
['5', '5', '5', '3']

Assigning a new key to specific key-value pairs in a list of python dictionary

I have the following list of python dictionary:
x=[{'a': '1',
'b': '2',
'c': '3',
'd': '4',
'e': '5',
'f': '6',
'g': '7'}]
My desired output:
x=[{'g': '7', 'AA': {'a': '1', 'b': '2', 'c': '3', 'd': '4', 'e': '5', 'f': '6'}}]
I was able to assign a new key in the x list to specific key-value pairs, however, I'm appending it to the current list and getting the following output:
x=[{'a': '1',
'b': '2',
'c': '3',
'd': '4',
'e': '5',
'f': '6',
'AA':{'a':'1','b':'2','c':'3','d':'4','e':'5','f':'6'},
{'g':'7'}]
Eventually, I had to remove the keys a through f.
Current working solution:
for k in x:
k['AA'] = {u: k[u] for u in sorted(k.keys())[:6]}
rem_list = ['a', 'b', 'c', 'd', 'e', 'f']
for k in rem_list:
for v in x:
v.pop(k)
I need to simply assign a new key to the corresponding key-value pairs on the fly without looping through the list twice.
Why not just create a new dictionary? It's much safer as it doesn't manipulate mutable dict data, and may cause other methods using this dict to mis-behave.
Try something like:
x=[{'a': '1',
'b': '2',
'c': '3',
'd': '4',
'e': '5',
'f': '6',
'g': '7'}]
new_dict = {'AA': {k: v for k, v in x[0].items() if k != 'g'}, 'g': x[0]['g']}

Convert a list of strings to a list of strings and ints

I have a dictionary of lists, each list has 3 elements, i want to convert the 2nd and 3rd element to ints from strings
dict = {1:['string', '2', '3',],
2:['string', '2', '3',],
3:['string', '2', '3',],}
to become:
dict = {1:['string', 2, 3,],
2:['string', 2, 3,],
3:['string', 2, 3,],}
Thank you
Firstly, don't name your dictionaries dict, as it's a reserved keyword and you don't wanna overwrite it.
Coming to your solution.
d = {
1: ['string', '23', '3'],
2: ['string', '2', '3'],
3: ['string', '2', '3'],
}
d2 = {
k: [
int(i) if i.isdigit() else i
for i in v
]
for k, v in d.items()
}
Will give you an output of:
{
1: ['string', '23', '3'],
2: ['string', '2', '3'],
3: ['string', '2', '3']
}
{
1: ['string', 23, 3],
2: ['string', 2, 3],
3: ['string', 2, 3]
}
If you dictionary has many elements you might not want to create a second dictionary in memory, but modify the existing one in-place:
data = {
1: ['string', '2', '3'],
2: ['string', '2', '3'],
3: ['string', '2', '3'],
}
for v in data.values():
v.append(int(v.pop(1)))
v.append(int(v.pop(1)))
print(data)
Output:
{1: ['string', 2, 3], 2: ['string', 2, 3], 3: ['string', 2, 3]}

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.

Resources