Dictionary deletion of values going out of index - python

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]]

Related

There is an array with some numbers. All numbers are equal except for one. How i can found only that number in python?

There is an array with some numbers. All numbers are equal except for one. How i can found only that number in python?
uniq([ 1, 1, 1, 2, 1, 1 ]) == 2
I use 'set' but it print me [1, 2]...
This is the simplest way to implement your problem:
def count_unique(s,lst):
for i in lst:
if(lst.count(i)==1):
return i
lst=list(map(int,input().split()))
s=list(set(lst))
print(count_unique(s,lst))
you can convert the list to a set to get all of items in the list and then by using count function find out which one of them only exists in the list only once.
for i in set(arr):
if arr.count(i) == 1:
print(i)
or list comprehension:
[i for i in set(arr) if arr.count(i) == 1]
this way you can get all the items in list that occur once.
this link might also help you.
from collections import Counter
def find_unique(list1):
count = Counter(list1)
if len(list1) >= 3:
for key, value in count.items():
if value == 1:
return key
I would use collections.Counter for this as follows:
import collections
x = [ 1, 1, 1, 2, 1, 1 ]
occurs = collections.Counter(x)
for k, v in occurs.items():
if v == 1:
print(k)
output:
2
Explanation: occurs is dict with pairs of value - how many times it appears, I print all values which appeared exactly once.

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)

Searching for an exact values in a Dictionary

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]

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]

Find last occurrence of any item of one list in another list in python

I have the following 2 lists in python:
ll = [500,500,500,501,500,502,500]
mm = [499,501,502]
I want to find out the position of last occurence of any item in mm, in the list ll. I can do this for a single element like this:
len(ll) - 1 - ll[::-1].index(502)
>> 5
Here ll[::-1].index(502) provides position of last occurence of 502 and len(ll) - 1 gives the total length.
How do I extend this to work for the entire list mm? I know I can write a function, but is there a more pythonic way
If you want all the last indices of each item in ll present in mm, then:
ll = [500,500,500,501,500,502,500]
mm = [499,501,502]
d = {v:k for k,v in enumerate(ll) if v in mm}
# {501: 3, 502: 5}
It's probably worth creating a set from mm first to make it an O(1) lookup, instead of O(N), but for three items, it's really not worth it.
Following #Apero's concerns about retaining missing indices as None and also using a hash lookup to make it an O(1) lookup...
# Build a key->None dict for all `mm`
d = dict.fromkeys(mm)
# Update `None` values with last index using a gen-exp instead of dict-comp
d.update((v,k) for k,v in enumerate(ll) if v in d)
# {499: None, 501: 3, 502: 5}
results = {}
reversed = ll[::-1]
for item in mm:
try:
index = ((len(ll) - 1) - reversed.index(item))
except ValueError:
index = None
finally:
results[item] = index
print results
Output:
{499: None, 501: 3, 502: 5}
You can do this with a list comprehension and the max function. In particular, for each element in ll, iterate through mm to create a list of indices where ll[i] = mm[i], and take the max of this list.
>>> indices = [ max([-1] + [i for i, m in enumerate(mm) if m == n]) for n in ll ]
>>> indices
[-1, -1, -1, 1, -1, 2, -1]
Note that you need to add [-1] in case there are no matching indices in mm.
All this being said, I don't think it's more Python-ic than writing a function and using a list comprehension (as you alluded to in your question).

Categories