searching element of 1-D list in 2-D list - python

I have two lists, one is of form:
A = ["qww","ewq","ert","ask"]
B = [("qww",2) ,("ert",4) , ("qww",6), ("ewq" , 5),("ewq" , 10),("ewq" , 15),("ask",11)]
I have to process such that final output is
C = A = [("qww",8),("ewq",20),("ert",4),("ask",11)]
for that I written code:
# in code temp_list is of form A
# in code total_list is of form B
# in code final is of form C
def ispresent(key,list):
for qwerty in list:
if qwerty == key:
return 1
else:
return 0
def indexreturn(key,list):
counter = 0
for qwerty in list:
if qwerty != key:
counter = counter + 1
else:
return counter
def mult_indexreturn(key,list):
for i in range(len(list)):
if key == list[i][0]:
return i
final = map(lambda n1, n2: (n1,n2 ), temp_list,[ 0 for _ in range(len(temp_list))])
for object2 in total_list:#****
for object1 in temp_list:
if object2 == object1:
final[ indexreturn(object2,final) ][1] = final[ indexreturn(object2, final) ][1] + object2[mult_indexreturn(object2,total_list)][1]#total_list[ mult_indexreturn(object2,total_list) ][1]
print(final)
it should give output as C type list, but giving nothing
but C = [("qww",0),("ewq",0),("ert",0),("ask",0)]
according to me the main problem is in my looping part ( with **** comment), is there problem with logic or something else.
I gave in lot of codes, so that you can understand how my code working

You can build a dictionary using the method fromkeys() and subsequently you can use the for loop to accumulate integers:
A = ["qww","ewq","ert","ask"]
B = [("qww",2) ,("ert",4) , ("qww",6), ("ewq" , 5),("ewq" , 10),("ewq" , 15),("ask",11)]
C = dict.fromkeys(A, 0)
# {'qww': 0, 'ewq': 0, 'ert': 0, 'ask': 0}
for k, v in B:
C[k] += v
C = list(C.items())
# [('qww', 8), ('ewq', 30), ('ert', 4), ('ask', 11)]

Try this:
from collections import defaultdict
result = defaultdict(int)
for i in A:
result[i] = sum([j[1] for j in B if j[0] == i])
then tuple(result.items()) will be your out put.
Or you can do it in just one line:
result = tuple({i:sum([j[1] for j in B if j[0] == i]) for i in A}.items())

Using collection.defaultdict
Ex:
from collections import defaultdict
A = ["qww","ewq","ert","ask"]
B = [("qww",2) ,("ert",4) , ("qww",6), ("ewq" , 5),("ewq" , 10),("ewq" , 15),("ask",11)]
result = defaultdict(int)
for key, value in B:
if key in A: #Check if Key in A.
result[key] += value #Add Value.
print(result)
Output:
defaultdict(<type 'int'>, {'qww': 8, 'ert': 4, 'ewq': 30, 'ask': 11})

Related

Match list's index based off its value

I am new to Python and working on a problem where I have to match a list of indices to a list of value with 2 conditions:
If there is a repeated index, then the values should be summed
If there is no index in the list, then value should be 0
For example, below are my 2 lists: 'List of Inds' and 'List of Vals'. So at index 0, my value is 5; at index 1, my value is 4; at index 2, my value is 3 (2+1), at index 3, may value 0 (since no value associated with the index) and so on.
Input:
'List of Inds' = [0,1,4,2,2]
'List Vals' = [5,4,3,2,1]
Output = [5,4,3,0,3]
I have been struggling with it for few days and can't find anything online that can point me in the right direction. Thank you.
List_of_Inds = [0,1,4,2,2]
List_Vals = [5,4,3,2,1]
dic ={}
i = 0
for key in List_of_Inds:
if key not in dic:
dic[key] = 0
dic[key] = List_Vals[i]+dic[key]
i = i+1
output = []
for key in range(0, len(dic)+1):
if key in dic:
output.append(dic[key])
else:
output.append(0)
print(dic)
print(output)
output:
{0: 5, 1: 4, 4: 3, 2: 3}
[5, 4, 3, 0, 3]
The following code works as desired. In computer science it is called "Sparse Matrix" where the data is kept only for said indices, but the "virtual size" of the data structure seems large from the outside.
import logging
class SparseVector:
def __init__(self, indices, values):
self.d = {}
for c, indx in enumerate(indices):
logging.info(c)
logging.info(indx)
if indx not in self.d:
self.d[indx] = 0
self.d[indx] += values[c]
def getItem(self, key):
if key in self.d:
return self.d[key]
else:
return 0
p1 = SparseVector([0,1,4,2,2], [5,4,3,2,1])
print p1.getItem(0);
print p1.getItem(1);
print p1.getItem(2);
print p1.getItem(3);
print p1.getItem(4);
print p1.getItem(5);
print p1.getItem(6);
Answer code is
def ans(list1,list2):
dic={}
ans=[]
if not(len(list1)==len(list2)):
return "Not Possible"
for i in range(0,len(list1)):
ind=list1[i]
val=list2[i]
if not(ind in dic.keys()):
dic[ind]=val
else:
dic[ind]+=val
val=len(list1)
for i in range(0,val):
if not(i in dic.keys()):
ans.append(0)
else:
ans.append(dic[i])
return ans
To test:
print(ans([0,1,4,2,2], [5,4,3,2,1]))
output:
[5, 4, 3, 0, 3]
Hope it helps
Comment if you dont understand any step
what you can do is sort the indexes and values in an ascending order, and then sum it up. Here is an example code:
import numpy as np
ind = [0,1,4,2,2]
vals = [5,4,3,2,1]
points = zip(ind,vals)
sorted_points = sorted(points)
new_ind = [point[0] for point in sorted_points]
new_val = [point[1] for point in sorted_points]
output = np.zeros((len(new_ind)))
for i in range(len(new_ind)):
output[new_ind[i]] += new_val[i]
In this code, the index values are sorted to be in ascending order and then the value array is rearranged according to the sorted index array. Then, using a simple for loop, you can sum the values of each existing index and calculate the output.
This is a grouping problem. You can use collections.defaultdict to build a dictionary mapping, incrementing values in each iteration. Then use a list comprehension:
indices = [0,1,4,2,2]
values = [5,4,3,2,1]
from collections import defaultdict
dd = defaultdict(int)
for idx, val in zip(indices, values):
dd[idx] += val
res = [dd[idx] for idx in range(max(dd) + 1)]
## functional alternative:
# res = list(map(dd.get, range(max(dd) + 1)))
print(res)
# [5, 4, 3, 0, 3]

For loops in a dictionary and if statement

Firstly, I have to say that i'm a beginner in python.
Then, here is my problem :
I have a dictionary like this one :
dic = {}
dic["a", 1] = 0
dic["a", 2] = 2
dic["b", 1] = 5
dic["b", 2] = 0
...
And I want to do a for-loop with this dictionary to test all the keys' pair and find which ones are equivalent to 0 in a if statement.
I thought of that :
for [co, l], ch in dic.items():
if [co, l] == 0:
But the if statement is never true, so I can't do anything.
Does anyone could provide me some help, please ?
Thanks
[co, l] is the key (or copy of it); it is a list with 2 items, and cannot be equal to 0. Instead you want to test the ch value and then perhaps do something with the key.
dic = {}
dic["a", 1] = 0
dic["a", 2] = 2
dic["b", 1] = 5
dic["b", 2] = 0
...
for [co, l], ch in dic.items():
if ch == 0:
print("The value for key {}, {} was 0".format(co, l))
Or if you want to iterate by the key:
for key in dic:
if dic[key] == 0:
print("The value for key {} was 0".format(key))
As per the comments:
for ch in dic.items():
if ch == 0:
[co, l] is never 0. I think you mean to test ch.
for [co, l], ch in dic.items():
... print [co, l], ch
...
['a', 1] 0
['b', 2] 0
['b', 1] 5
['a', 2] 2

Find duplicates of two columns from csv

I want to find duplicate values of one column and replaced with value of another column of csv which has multiple columns. So first I put two columns from the csv to the dictionary. Then I want to find duplicate values of dictionary that has string values and keys. I tried with solutions of remove duplicates of dictionary but got the error as not hashable or no result. Here is the first part of code.
import csv
from collections import defaultdict
import itertools as it
mydict = {}
index = 0
reader = csv.reader(open(r"computing.csv", "rb"))
for i, rows in enumerate(reader):
if i == 0:
continue
if len(rows) == 0:
continue
k = rows[3].strip()
v = rows[2].strip()
if k in mydict:
mydict[k].append(v)
else:
mydict[k] = [v]
#mydict = hash(frozenset(mydict))
print mydict
d = {}
while True:
try:
d = defaultdict(list)
for k,v in mydict.iteritems():
#d[frozenset(mydict.items())]
d[v].append(k)
except:
continue
writer = csv.writer(open(r"OLD.csv", 'wb'))
for key, value in d.items():
writer.writerow([key, value])
Your question is unclear. So I hope I got it right.
Please give an example of input columns and the desired output columns.
Please give a printout of the error and let us know which line caused the error.
if column1=[1,2,3,1,4] and column2=[a,b,c,d,e] do you want the output to be n_column1=[a,2,3,d,4] and column2 =[1,b,c,d,e]
I imagine the exception was in d[v].append(k) since clearly v is a list. you cannot use a list as a key in a dictionary.
In [1]: x = [1,2,3,1,4]
In [2]: y = ['a','b','c','d','e']
In [5]: from collections import defaultdict
In [6]: d = defaultdict(int)
In [7]: for a in x:
...: d[a] += 1
In [8]: d
Out[8]: defaultdict(<type 'int'>, {1: 2, 2: 1, 3: 1, 4: 1})
In [9]: x2 = []
In [10]: for a,b in zip(x,y):
....: x2.append(a if d[a]==1 else b)
....:
In [11]: x
Out[11]: [1, 2, 3, 1, 4]
In [12]: x2
Out[12]: ['a', 2, 3, 'd', 4]
In that case, I guess if I had to change your code to fit. I'd do something like that:
import csv
from collections import defaultdict
import itertools as it
mydict = {}
index = 0
reader = csv.reader(open(r"computing.csv", "rb"))
histogram = defaultdict(int)
k = []
v = []
for i, rows in enumerate(reader):
if i == 0:
continue
if len(rows) == 0:
continue
k.append(rows[3].strip())
v.append(rows[2].strip())
item = k[-1]
histogram[item] += 1
output_column = []
for first_item, second_item in zip(k,v):
output_column.append(first_item if histogram[first_item]==1 else second_item)
writer = csv.writer(open(r"OLD.csv", 'wb'))
for c1, c2 in zip(output_column, v):
writer.writerow([c1, c2])

Count values by key in dictionary

I look for something that will count values in dict (automatically)without use a list of element
d = {}
d["x1"] = "1"
{'x1':'1'}
d["x1"] = "2"
{'x1':'2'}
d["x1"] = "3"
{'x1':'3'}
d["x2"] = "1"
{'x1':'3', 'x2':'1'}
ect..
I try create a list them using
for x in list:
d[x] = list.count(x)
But when I created a list , I receive a memory error
Are you sure you want to use a dict to do it? It seems a Counter or a defaultdict suits your need more.
>>> d = collections.Counter()
>>> d['x1'] += 1
>>> d
Counter({'x1': 1})
>>> d['x1'] += 1
>>> d
Counter({'x1': 2})
>>> d['x2'] += 1
>>> d
Counter({'x1': 2, 'x2': 1})
You could also convert a sequence to a counter:
>>> collections.Counter(['x1', 'x1', 'x2'])
Counter({'x1': 2, 'x2': 1})
Use a defaultdict:
>>> d = defaultdict(int)
>>> d['foo'] += 1
>>> d['foo'] += 1
>>> d['bar'] += 1
>>> for i in d:
... print i,d[i]
...
foo 2
bar 1
You can use dict in the following manner -
d['x1'] = d.get('x1', 0) + 1
The second argument in get specifies the object to return if the key supplied in the first argument is not found.
Applying this on your example:
from pprint import pprint
d = {}
d['x1'] = d.get('x1', 0) + 1
d['x1'] = d.get('x1', 0) + 1
d['x1'] = d.get('x1', 0) + 1
d['x2'] = d.get('x2', 0) + 1
pprint(d) # will print {'x1': 3, 'x2': 1}

Python: finding keys with unique values in a dictionary?

I receive a dictionary as input, and want to return a list of keys for which the dictionary values are unique in the scope of that dictionary.
I will clarify with an example. Say my input is dictionary a, constructed as follows:
a = dict()
a['cat'] = 1
a['fish'] = 1
a['dog'] = 2 # <-- unique
a['bat'] = 3
a['aardvark'] = 3
a['snake'] = 4 # <-- unique
a['wallaby'] = 5
a['badger'] = 5
The result I expect is ['dog', 'snake'].
There are obvious brute force ways to achieve this, however I wondered if there's a neat Pythonian way to get the job done.
I think efficient way if dict is too large would be
countMap = {}
for v in a.itervalues():
countMap[v] = countMap.get(v,0) + 1
uni = [ k for k, v in a.iteritems() if countMap[v] == 1]
Here is a solution that only requires traversing the dict once:
def unique_values(d):
seen = {} # dict (value, key)
result = set() # keys with unique values
for k,v in d.iteritems():
if v in seen:
result.discard(seen[v])
else:
seen[v] = k
result.add(k)
return list(result)
Note that this actually is a bruteforce:
l = a.values()
b = [x for x in a if l.count(a[x]) == 1]
>>> b = []
>>> import collections
>>> bag = collections.defaultdict(lambda: 0)
>>> for v in a.itervalues():
... bag[v] += 1
...
>>> b = [k for (k, v) in a.iteritems() if bag[v] == 1]
>>> b.sort() # optional
>>> print b
['dog', 'snake']
>>>
A little more verbose, but does need only one pass over a:
revDict = {}
for k, v in a.iteritems():
if v in revDict:
revDict[v] = None
else:
revDict[v] = k
[ x for x in revDict.itervalues() if x != None ]
( I hope it works, since I can't test it here )
What about subclassing?
class UniqueValuesDict(dict):
def __init__(self, *args):
dict.__init__(self, *args)
self._inverse = {}
def __setitem__(self, key, value):
if value in self.values():
if value in self._inverse:
del self._inverse[value]
else:
self._inverse[value] = key
dict.__setitem__(self, key, value)
def unique_values(self):
return self._inverse.values()
a = UniqueValuesDict()
a['cat'] = 1
a['fish'] = 1
a[None] = 1
a['duck'] = 1
a['dog'] = 2 # <-- unique
a['bat'] = 3
a['aardvark'] = 3
a['snake'] = 4 # <-- unique
a['wallaby'] = 5
a['badger'] = 5
assert a.unique_values() == ['dog', 'snake']
Here's another variation.
>>> import collections
>>> inverse= collections.defaultdict(list)
>>> for k,v in a.items():
... inverse[v].append(k)
...
>>> [ v[0] for v in inverse.values() if len(v) == 1 ]
['dog', 'snake']
I'm partial to this because the inverted dictionary is such a common design pattern.
You could do something like this (just count the number of occurrences for each value):
def unique(a):
from collections import defaultdict
count = defaultdict(lambda: 0)
for k, v in a.iteritems():
count[v] += 1
for v, c in count.iteritems():
if c <= 1:
yield v
Use nested list comprehensions!
print [v[0] for v in
dict([(v, [k for k in a.keys() if a[k] == v])
for v in set(a.values())]).values()
if len(v) == 1]

Categories

Resources