Searching for an exact values in a Dictionary - python

I have a Dictionary and I want to search for the keys which correspond to a particular value I need (S009 and S007 in this case)
I wrote the following code but I get nothing from it
Here is my Code:
def find():
L = [{"V": "S001"},
{"V": "S002"},
{"V": "S001"},
{"V": "S001"},
{"V": "S001"},
{"V1": "S002"},
{"V111": "S005"},
{"V2": "S005"},
{"V": "S009"},
{"V3": "S007"}]
L1 = []
for y in range (len(L)) :
for j in L[y].values():
L1.append(j)
L2=[]
for z in L1:
if z not in L2:
L2.append(z)
count =0
l3=[]
s = set(L1)
for z in L2:
for y in L1:
if z in L2:
count =count +1
if count == 2:
l3.append(z)
for s in l3:
print(s)
def main():
find()
main()
My code explained: First, I took all the values in a list and called it L1. Then I get all the values without being copied in L2. Then, I want to search if an element of L2 exists in L1. After this loop, if the count became only one so this is the value I'm looking for & I append it to an empty list called l3

You can do it in two steps. First extract all the values from L:
values = []
for i in L:
for v in i.values():
values.append(v)
Or as a list comprehension:
values = [v for i in L for v in i.values()]
Then filter out the items with count more than 1:
result = [i for i in values if values.count(i) == 1]
print (result)
Result:
['S009', 'S007']

What you've defined above as L is a list of individual dictionaries. I'm not sure this is what was intended. You said you're expected output should be 's009' and 's007', so I'm going to assume that, perhaps, you intended L to just be a list of the values of each individual dictionary. In that's the case,
L = ["S001", "S002", "S001", "S001", "S001", "S002", "S005", "S005", "S009", "S007"]
One of the easiest ways to count the number of items of a list is to use a Counter from the collections module.
Then just create the Counter with the L as the only argument
from collections import Counter
c = Counter(L)
print(c)
Counter({'S001': 4, 'S002': 2, 'S005': 2, 'S009': 1, 'S007': 1})
Now you can see how many instances of each element of L exist. From there you can just use a little list comprehension to filter out anything that doesn't have one instance.
result = [key for key, value in c.items() if value == 1]
print(result)
['S009', 'S007']
All the code:
from collections import Counter
L = ["S001", "S002", "S001", "S001", "S001", "S002", "S005", "S005", "S009", "S007"]
c = Counter(L)
result = [key for key, value in c.items() if value == 1]

Related

How can i create a dictionary from 2 lists with one as the key and the other as as the value with only loops? Without using zip() or enumerate()

I wanna achieve this without any libraries or special functions just loops. I wanna have a main program that takes in 2 inputs which are the 2 lists and returns the dictionary like shown below.
Please enter the item names: Cans, bottles, boxes, jugs
please enter quantities : 20,34,10
output : {'Cans':'20','bottles':'34','boxes':'10','jugs':'0'}
If the list of items is longer than the quantities then the quantity becomes automatically 0 as it did with the jugs above.
If the List of Quantity is longer than the items list then the item should automatically become 'unknown object_1' with the number changing accordingly.
Split with comma as delimiter. Fill values with zero for a number of iterations equal to the difference in length between keys and values.
Then use dict comprehension to build your dict. This with the zip built-in function.
keys = 'a,b,c,d'
values = '1,2,3'
keys = keys.split(',')
values = values.split(',')
for i in range(len(keys) - len(values)):
values.append('0')
dct = {}
for i in range(len(keys)):
dct[keys[i]] = values[i]
print(dct)
Output:
{'a': '1', 'b': '2', 'c': '3', 'd': '0'}
This uses only built-in calls so it fits your requirements at best. At the OP requirements it is not using the zip function.
item_names = ['Cans', 'Bottles', 'boxes', 'jugs']
quantities = [20, 34, 10]
output_dict = {}
for i, item in enumerate(item_names):
if i > len(quantities) - 1:
output_dict.update({item : 0})
else:
output_dict.update({item : quantities[i]})
a = list(input().split(','))
b = list(map(int, input().split(',')))
res = {}
for i in range(len(a)):
res[a[i]] = b[i] if i < len(b) else 0
print(res)
list1 = ['cans','Bottles','Boxes','Jugs']
list2 = [1,2,3]
res = {}
for i, element in enumerate(list1):
try:
res[element] = list2[i]
except IndexError:
res[element] = 0
print(res)
Edited code without enumerate or zip:
list1 = ['cans','Bottles','Boxes','Jugs']
list2 = [1,2,3]
res = {}
i=0
for element in list1:
try:
res[element] = list2[i]
except IndexError:
res[element] = 0
i+=1
print(res)
```

Find duplicates in a list of strings differing only in upper and lower case writing

I have a list of strings that contains 'literal duplicates' and 'pseudo-duplicates' which differ only in lower- and uppercase writing. I am looking for a function that treats all literal duplicates as one group, returns their indices, and finds all pseudo-duplicates for these elements, again returning their indices.
Here's an example list:
a = ['bar','bar','foo','Bar','Foo','Foo']
And this is the output I am looking for (a list of lists of lists):
dupe_list = [[[0,1],[3]],[[2],[4,5]]]
Explanation: 'bar' appears twice at the indexes 0 and 1 and there is one pseudo-duplicate 'Bar' at index 3. 'foo' appears once at index 2 and there are two pseudo-duplicates 'Foo' at indexes 4 and 5.
Here is one solution (you didn't clarify what the logic of list items will be and i considered that you want the items in lower format as they are met from left to right in the list, let me know if it must be different):
d={i:[[], []] for i in set(k.lower() for k in a)}
for i in range(len(a)):
if a[i] in d.keys():
d[a[i]][0].append(i)
else:
d[a[i].lower()][1].append(i)
result=list(d.values())
Output:
>>> print(result)
[[[0, 1], [3]], [[2], [4, 5]]]
Here's how I would achieve it. But you should consider using a dictionary and not a list of list of list. Dictionaries are excellent data structures for problems like this.
#default argument vars
a = ['bar','bar','foo','Bar','Foo','Foo']
#initalize a dictionary to count occurances
a_dict = {}
for i in a:
a_dict[i] = None
#loop through keys in dictionary, which is values from a_list
#loop through the items from list a
#if the item is exact match to key, add index to list of exacts
#if the item is similar match to key, add index to list of similars
#update the dictionary key's value
for k, v in a_dict.items():
index_exact = []
index_similar = []
for i in range(len(a)):
print(a[i])
print(a[i] == k)
if a[i] == str(k):
index_exact.append(i)
elif a[i].lower() == str(k):
index_similar.append(i)
a_dict[k] = [index_exact, index_similar]
#print out dictionary values to assure answer
print(a_dict.items())
#segregate values from dictionary to its own list.
dup_list = []
for v in a_dict.values():
dup_list.append(v)
print(dup_list)
Here is the solution. I have handled the situation where if there are only pseudo duplicates present or only literal duplicates present
a = ['bar', 'bar', 'foo', 'Bar', 'Foo', 'Foo', 'ka']
# Dictionaries to store the positions of words
literal_duplicates = dict()
pseudo_duplicates = dict()
for index, item in enumerate(a):
# Treates words as literal duplicates if word is in smaller case
if item.islower():
if item in literal_duplicates:
literal_duplicates[item].append(index)
else:
literal_duplicates[item] = [index]
# Handle if only literal_duplicates present
if item not in pseudo_duplicates:
pseudo_duplicates[item] = []
# Treates words as pseudo duplicates if word is in not in smaller case
else:
item_lower = item.lower()
if item_lower in pseudo_duplicates:
pseudo_duplicates[item_lower].append(index)
else:
pseudo_duplicates[item_lower] = [index]
# Handle if only pseudo_duplicates present
if item not in literal_duplicates:
literal_duplicates[item_lower] = []
# Form final list from the dictionaries
dupe_list = [[v, pseudo_duplicates[k]] for k, v in literal_duplicates.items()]
Here is the simple and easy to understand answer for you
a = ['bar','bar','foo','Bar','Foo','Foo']
dupe_list = []
ilist = []
ilist2 =[]
samecase = -1
dupecase = -1
for i in range(len(a)):
if a[i] != 'Null':
ilist = []
ilist2 = []
for j in range(i+1,len(a)):
samecase = -1
dupecase = -1
# print(a)
if i not in ilist:
ilist.append(i)
if a[i] == a[j]:
# print(a[i],a[j])
samecase = j
a[j] = 'Null'
elif a[i] == a[j].casefold():
# print(a[i],a[j])
dupecase = j
a[j] = 'Null'
# print(samecase)
# print(ilist,ilist2)
if samecase != -1:
ilist.append(samecase)
if dupecase != -1:
ilist2.append(dupecase)
dupe_list.append([ilist,ilist2])
a[i]='Null'
print(dupe_list)

I want to write a function that takes a list and returns a count of total number of duplicate elements in the list

I have tried this, for some unknown reason when it prints h, it prints None, so i thought if it counts the number of None printed then divided by 2 it will give the number of duplicates, but i cant use function count here
a= [1,4,"hii",2,4,"hello","hii"]
def duplicate(L):
li=[]
lii=[]
h=""
for i in L:
y= L.count(i)
if y>1:
h=y
print h
print h.count(None)
duplicate(a)
Use the Counter container:
from collections import Counter
c = Counter(['a', 'b', 'a'])
c is now a dictionary with the data: Counter({'a': 2, 'b': 1})
If you want to get a list with all duplicated elements (with no repetition), you can do as follows:
duplicates = filter(lambda k: c[k] > 1, c.iterkeys())
If you want to only count the duplicates, you can then just set
duplicates_len = len(duplicates)
You can use a set to get the count of unique elements, and then compare the sizes - something like that:
def duplicates(l):
uniques = set(l)
return len(l) - len(uniques)
i found an answer which is
a= [1,4,"hii",2,4,"hello",7,"hii"]
def duplicate(L):
li=[]
for i in L:
y= L.count(i)
if y>1:
li.append(i)
print len(li)/2
duplicate(a)
the answer by egualo is much better, but here is another way using a dictionary.
def find_duplicates(arr):
duplicates = {}
duplicate_elements = []
for element in arr:
if element not in duplicates:
duplicates[element] = False
else:
if duplicates[element] == False:
duplicate_elements.append(element)
duplicates[element] = True
return duplicate_elements
It's pretty simple and doesn't go through the lists twice which is kind of nice.
>> test = [1,2,3,1,1,2,2,4]
>> find_duplicates(test)
[1, 2]

Dictionary deletion of values going out of index

I have a dictionary
k = {'a':[7,2,3],'b':[7,2,7], 'c': [8,9,10]}
where is each val is a list. I want to delete the ith term(depending on condition) in a val without going out of range. this is code for it
for i in range(len(k['a'])):
if k['a'][i] == k['b'][i]:
pass
else:
for key in k:
del [k[key][i]]
This would work return a dictionary equivalent to this
{'a':[7,2],'b':[7,2], 'c': [8,9]}
However if the dictionary was this
k = {'a':[6,2,3],'b':[7,2,7], 'c': [8,9,10]}
I would get this Error
list index out of range
How I delete key vals so I don't get this error?
The issue is that when you delete one item from each array, the size of these arrays decreases by one. Thus, the main loop becomes one iteration too long.
An illustration of the problem:
>>> a = [1, 2, 3]
>>> i = 2
>>> a[i]
3
>>> len(a)
3
>>> del [a[1]]
>>> a
[1, 3]
>>> len(a)
2
>>> a[i] # used to work
IndexError: list index out of range
In order for the index and the loop duration to work out you need to do something like this:
i = 0
while i < len(k['a']):
if k['a'][i] == k['b'][i]:
i += 1
else:
for key in k:
del [k[key][i]]

What is the fastest way to compare two lists with thounsands of entries?

I have
list1 = ["value1;value2;value3;value4;fdsa",]
list2 = ["value1;value2;value3;value4;asdf",]
What I need to do is go through each list2 entry, compare values with index 0,1,2,3 and if they match - use the fourth entry in another method.
Right now I have something like this:
for entry1 in list1:
for entry2 in list2:
if entry2.split(';')[0] == entry1.split(';')[0]: #... etc, compare first 3 values
print(entry2.split(';')[4]) # edited out my code
#do stuff
This obviously works, but it is incredibly slow. I am using Python 2.78
Firstly create a dictionary from list2's items with first four items as keys and the 5th item as value.
dct = dict(x.rsplit(';', 1) for x in list2)
And then loop over list1 and check if the key exist in the above dict:
for x in list1:
k, v = x.rsplit(';', 1)
if k in dct:
val = dct[k]
#do something with val
In case list2 contains repeated keys with different values then you may need to store them in a list:
from collections import defaultdict
d = defaultdict(list)
for x in list2:
k, v = x.rsplit(';', 1)
d[k].append(v)
for x in list1:
k, v = x.rsplit(';', 1)
for val in d[k]:
#do something with val
You are splitting the entries from list1 multiple times. If you split them once and store the result in a variable, you can reuse it in the inner loop.
Try like this:-
colon_sep_list1=list1.split(";")
colon_sep_list2=list2.split(";")
for index in range(len(colon_sep_list2)):
if index <=len(colon_sep_list1):
if colon_sep_list1[index]==colon_sep_list2[index]:
print colon_sep_list2[4]
break
For avoiding to split the list2 entries every time for compare with list1 entries store the split list in a separate variable and work with them :
>>> l2=map(lambda x:x.split(';'),list2)
>>> [j[4] for i in list1 for j in l2 if i.split(';')[0] == j[0]]
['asdf']
Benchmarking :
list1 = ["value1;value2;value3;value4;fdsa",]
list2 = ["value1;value2;value3;value4;asdf",]
def test1():
l2=map(lambda x:x.split(';'),list2)
new=[j[4] for i in list1 for j in l2 if i.split(';')[0] == j[0]]
def test2():
new=[]
for entry1 in list1:
for entry2 in list2:
if entry2.split(';')[0] == entry1.split(';')[0]: #... etc, compare first 3 values
new.append(entry2.split(';')[4]) # edited out my code
#do stuff
if __name__ == '__main__':
import timeit
print 'test 1 : ',timeit.timeit("test1()", setup="from __main__ import test1")
print 'test 2 : ',timeit.timeit("test2()", setup="from __main__ import test2")
result :
test 1 : 1.24494791031
test 2 : 1.34099817276

Categories