Find item index in list - python

This is a very simple question but I can't seem to understand why I am not getting it.
def listindex():
li = ['a', 'e', 'a', 'd', 'b', 'a', 'e']
for x in li:
if x == 'a':
print(li.index(x))
Result:
0
0
0
Expected Result:
0
2
5
Although it iterates over all the item I only get first item index, why is it? Also advise even though its pretty simple.

index returns the index of the first element only. From the docs
Return the index in the list of the first item whose value is x. It is an error if there is no such item.
Use enumerate instead. When you iterate using enumerate you can access the element and its index on the loop:
>>> li = ['a', 'e', 'a', 'd', 'b', 'a', 'e']
>>> for i,element in enumerate(li):
... if element == 'a':
... print(i)
...
0
2
5

li = ['a', 'e', 'a', 'd', 'b', 'a', 'e']
Use List Comprehension:
[i for i, x in enumerate(li) if x=='a']
Output: [0, 2, 5]

Use keyword enumerate() this will generate a counter from 0 to N.
for i, x in enumerate(li):
So i will contain the indexes for li.

Related

Check how many items from one list appear in another list

If I have 2 lists, for an example:
list_1 = ['a', 'A']
list_2 = ['a', 'A', 'A', 'b', 'b', 'b', 'b']
How can I make a count to see how many times the items from list_1 appear in list_2?
So in this case it should return 3.
list_1 = ['a', 'A']
list_2 = ['a', 'A', 'A', 'b', 'b', 'b', 'b']
found = 0
for x in list_1:
for y in list_2:
if x == y:
found += 1
print(found)
An efficient O(n) method using a set as reference:
list_1 = ['a', 'A']
list_2 = ['a', 'A', 'A', 'b', 'b', 'b', 'b']
set_1 = set(list_1)
count = 0
for e in list_2:
if e in set_1:
counter += 1
Output: 3
A one liner:
sum([x == y for x in list_1 for y in list_2])
Another solution, which could be beneficial in other cases, because the Counter()- object returns a dictionary with the already summed up elements
from collections import Counter
list_1 = ['a', 'A']
list_2 = ['a', 'A', 'A', 'b', 'b', 'b', 'b']
c = Counter(list_2)
print(sum([c[x] for x in list_1]))
Just use count for lists:
print(list_2.count(list_1[0]) + list_2.count(list_1[1]))
or in a loop:
sum_ = 0
for i in range(len(list_1)):
sum_ += list_2.count(list_1[i])
print(sum_)

Deleting elements of a list based on a condition

I have a list of elements from which I want to remove those elements whose count is less than or equal to 2 in all the list.
For example:
A = [['a','b','c'],['b','d'],['c','d','e'],['c','e','f'],['b','c','e','g']]
I want to remove 'a', 'd', 'f', 'g' from A and store the rest in B so that the list becomes:
B = [['b','c'],['b'],['c','e'],['c','e'],['b','c','e']]
I created a dictionary which will store all the count of elements and based on that I want to remove the elements with count less than or equal to 2.
Below is the code which I have written so far.
for i in range(len(A)):
for words in A[i]:
word_count[words] +=1
B = [A[i] for i in range(len(A)) if word_count[words]<2]
You can use collections.Counter:
from collections import Counter
import itertools
A = [['a','b','c'],['b','d'],['c','d','e'],['c','e','f'],['b','c','e','g']]
c = Counter(itertools.chain(*A))
new_a = [[b for b in i if c[b] > 2] for i in A]
Output:
[['b', 'c'], ['b'], ['c', 'e'], ['c', 'e'], ['b', 'c', 'e']]
Before you add a new key to the dictionary, you have to check if the key exists. If not, just add the key to the dictionary. Otherwise, update the key's value.
A = [['a','b','c'],['b','d'],['c','d','e'],['c','e','f'],['b','c','e','g']]
word_count = {}
for i in range(len(A)):
for words in A[i]:
if words not in word_count:
word_count[words] = 0
word_count[words] += 1
Then filter the initial list using the created dictionary.
B = [[x for x in A[i] if word_count[x] > 2] for i in range(len(A))]
print(B)
Output
[['b', 'c'], ['b'], ['c', 'e'], ['c', 'e'], ['b', 'c', 'e']]

Reverse the frequency count in python

Say, I have a data containing an item in line[1] followed by its frequency count in line[2]
Item Frequency.Count
A 5
B 4
C 3
D 2
E 1
But I want the output to be like:
Data
A
A
A
A
A
.
.
.
C
C
C
D
D
E
This is somewhat the reverse of the following code:
my_list = sorted(word_freq.items(), key = lambda x:x[1], reverse = True)
for word,freq in my_list:
print ("%‐10s %d" % (word, freq))
You might think this is a silly approach to a frequency analysis but I wanted to learn if there are reverse operation for counting frequencies, does anyone have an idea about unsorting the given data given there are two columns? Thanks so much for the advice.
Input list: l = [['A', 5], ['B', 3], ['C', 1]]
out_put=[]
[(out_put.extend([j for j in lst[0]*lst[1])] )) for lst in l]
out_put : ['A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'C']
IF you loop around your item and in second loop just replicate it no of times the frequency list than you are done i guess.Please try this approach
Do you want to do that ? I think this is what #Navin Dalal meant (not sure though).
with
> l
[['A', 5],
['B', 3],
['C', 1]]
you can get what you want:
> list("".join([i*j for i, j in l]))
['A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'C']
The key part being:
[i*j for i, j in l]
['AAAAA', 'BBB', 'C']
Because you can multiply a string a number of times given by an integer.
Hope this helps.

How do you remove a sublist if a certain element is not found at a specific position across all sublists?

In other words, if it's found that "f" is in the 4th position of the sublist, return that sublist, otherwise, exclude it if "f" is not found.
List = [['a','b','c','d','f'],['a','b','c','d','e'],['a','b','c','d','e'],['a','b','c','f','f'],['a','b']]
I have the following function which would work if all the sublists were the same size.
def Function(SM):
return filter(lambda x: re.search("f",str(x[4])),List)
IndexError: list index out of range
Desired_List = [['a','b','c','d','f'],['a','b','c','f','f']]
I'm reluctant to use a for loop, because of the speed and efficiency costs. Are there any alternatives that are just as quick?
You can use list comprehension:
lst = [['a','b','c'], ['a','b','c','d','f'],['a','b','c','d','e'],['a','b','c','d','e'],['a','b','c','f','f'],['a','b']]
lst_desired = [l for l in lst if len(l) >= 5 and l[4] == "f"]
print lst_desired
Output
[['a', 'b', 'c', 'd', 'f'], ['a', 'b', 'c', 'f', 'f']]
>>> li=[['a','b','c','d','f'],['a','b','c','d','e'],['a','b','c','d','e'],['a','b','c','f','f'],['a','b']]
>>> filter(lambda l: l[4:5]==['f'], li)
[['a', 'b', 'c', 'd', 'f'], ['a', 'b', 'c', 'f', 'f']]

Reiterating over lists and dictionaries

In the following code, why does my code not iterate properly? I'm probably missing one line but I can't figure out why it doesn't work.
I have a function with the following test case:
>>> borda([['A', 'B', 'C', 'D'], ['B', 'A', 'C', 'D'], ['B', 'C', 'D', 'A']])
('B', [5, 8, 4, 1])
Where lists in the parameter are rankings, each #1 rank gets 3 points, #2 gets 2 points, #3 gets 1 point, and no other ranks get anything. There may not necessarily four choices. The first element in the tuple should be the choice with the highest number of points, and the second element is the number of points each choice got, in alphabetical order.
I'm not done with the function, but I'm trying to get a dictionary of the choices as the keys in alphabetical order and the count of rankings as the values, but the output is a dictionary of only the very last element of the last list in the parameter.
L = ['A', 'B', 'C', 'D'] #This is referenced outside the function since it might change
D = {}
i = 0
num = 0
while num < len(L):
num += 1
for choice in L:
while i < len(parameter):
for item in parameter:
if item[0] == choice:
D[choice] = D.get(choice, 0) + 3
if item[1] == choice:
D[choice] = D.get(choice, 0) + 2
if item[2] == choice:
D[choice] = D.get(choice, 0) + 1
i += 1
return D
The way I'd do this is something like this:
import operator
from collections import defaultdict
listoflists = [['A', 'B', 'C', 'D'], ['B', 'A', 'C', 'D'], ['B', 'C', 'D', 'A']]
def borda(listoflists):
outdict = defaultdict(int)
for item in listoflists:
outdict[item[0]] += 3
outdict[item[1]] += 2
outdict[item[2]] += 1
highestitem = max(outdict.iteritems(), key=operator.itemgetter(1))[0]
outlist = [outdict[item[0]] for item in sorted(outdict.keys())]
return (highestitem, outlist)
Update:
I'm not sure why you wouldn't be able to import standard modules, but if for whatever reason you're forbidden from using the import statement, here's a version with only built-in functions:
listoflists = [['A', 'B', 'C', 'D'], ['B', 'A', 'C', 'D'], ['B', 'C', 'D', 'A']]
def borda(listoflists):
outdict = {}
for singlelist in listoflists:
# Below, we're just turning singlelist around in order to
# make use of index numbers from enumerate to add to the scores
for index, item in enumerate(singlelist[2::-1]):
if item not in outdict:
outdict[item] = index + 1
else:
outdict[item] += index + 1
highestitem = max(outdict.iteritems(), key=lambda i: i[1])[0]
outlist = [outdict[item[0]] for item in sorted(outdict.keys())]
return (highestitem, outlist)
If you had 2.7:
import operator
from collections import Counter
listoflists = [['A', 'B', 'C', 'D'], ['B', 'A', 'C', 'D'], ['B', 'C', 'D', 'A']]
def borda(listoflists):
outdict = sum([Counter({item[x]:3-x}) for item in listoflists for x in range(3]],
Counter())
highestitem = max(outdict.iteritems(), key=operator.itemgetter(1))[0]
outlist = [outdict[item[0]] for item in sorted(outdict.iteritems(),
key=operator.itemgetter(0))]
return (highestitem, outlist)
Look ma.. no loops :-)
Check out http://ua.pycon.org/static/talks/kachayev/index.html to see why this is better.

Categories