Related
I am trying to iterate through a double list but am getting the incorrect results. I am trying to get the count of each element in the list.
l = [['<s>', 'a', 'a', 'b', 'b', 'c', 'c', '</s>'], ['<s>', 'a', 'c', 'b', 'c', '</s>'], ['<s>', 'b', 'c', 'c', 'a', 'b', '</s>']]
dict = {}
for words in l:
for letters in words:
dict[letters] = words.count(letters)
for x in countVocabDict:
print(x + ":" + str(countVocabDict[x]))
at the moment, I am getting:
<s>:1
a:1
b:2
c:2
</s>:1
It seems as if it is only iterating through the last list in 'l' : ['<s>', 'b', 'c', 'c', 'a', 'b', '</s>']
but I am trying to get:
<s>: 3
a: 4
b: 5
c: 6
</s>:3
In each inner for loop, you are not adding to the current value of dict[letters] but set it to whatever amount is counted for the current sublist (peculiarly) named word.
Fixing your code with a vanilla dict:
>>> l = [['<s>', 'a', 'a', 'b', 'b', 'c', 'c', '</s>'], ['<s>', 'a', 'c', 'b', 'c', '</s>'], ['<s>', 'b', 'c', 'c', 'a', 'b', '</s>']]
>>> d = {}
>>>
>>> for sublist in l:
...: for x in sublist:
...: d[x] = d.get(x, 0) + 1
>>> d
{'<s>': 3, 'a': 4, 'b': 5, 'c': 6, '</s>': 3}
Note that I am not calling list.count in each inner for loop. Calling count will iterate over the whole list again and again. It is far more efficient to just add 1 every time a value is seen, which can be done by looking at each element of the (sub)lists exactly once.
Using a Counter.
>>> from collections import Counter
>>> Counter(x for sub in l for x in sub)
Counter({'<s>': 3, 'a': 4, 'b': 5, 'c': 6, '</s>': 3})
Using a Counter and not manually unnesting the nested list:
>>> from collections import Counter
>>> from itertools import chain
>>> Counter(chain.from_iterable(l))
Counter({'<s>': 3, 'a': 4, 'b': 5, 'c': 6, '</s>': 3})
The dictionary is being overwritten in every iteration, rather it should update
count_dict[letters] += words.count(letters)
Initialize the dictionary with defaultdict
from collections import defaultdict
count_dict = defaultdict(int)
As #Vishnudev said, you must add current counter. But dict[letters] must exists (else you'll get a KeyError Exception). You can use the get method of dict with a default value to avoir this:
l = [['<s>', 'a', 'a', 'b', 'b', 'c', 'c', '</s>'],
['<s>', 'a', 'c', 'b', 'c', '</s>'],
['<s>', 'b', 'c', 'c', 'a', 'b', '</s>']]
dict = {}
for words in l:
for letters in words:
dict[letters] = dict.get(letters, 0) + 1
As per your question, you seem to know that it only takes on the result of the last sublist. This happens because after every iteration your previous dictionary values are replaced and overwritten by the next iteration values. So, you need to maintain the previous states values and add it to the newly calculated values.
You can try this-
l = [['<s>', 'a', 'a', 'b', 'b', 'c', 'c', '</s>'], ['<s>', 'a', 'c', 'b', 'c', '</s>'], ['<s>', 'b', 'c', 'c', 'a', 'b', '</s>']]
d={}
for lis in l:
for x in lis:
if x in d:
d[x]+=1
else:
d[x]=1
So the resulting dictionary d will be as-
{'<s>': 3, 'a': 4, 'c': 6, 'b': 5, '</s>': 3}
I hope this helps!
I have the following:
a_list = [A,B,C]
r1 = range(1,5)
r2 = range(1,5)
r3 = range(1,5)
I would like to be able to find the various combinations of the elements in this list against the ranges. For example:
combi1 = [A, B, C, C, C]
combi2 = [A, A, B, C, C]
combi3 = [A, A, A, B, C]
combi4 = [A, B, B, C, C]
Etc.
I am able to do so if there were only 2 range, but I'm not sure how to fit 3 range in.
inc = range(1, 5)
desc = range(5, 1, -1)
combis = [list(itertools.chain(*(itertools.repeat(elem, n) for elem, n in zip(list, [i,j])))) for i,j in zip(inc,desc)]
SOLUTION:
def all_exist(avalue, bvalue):
return all(any(x in y for y in bvalue) for x in avalue)
combins = itertools.combinations_with_replacement(a_list, 5)
combins_list = [list(i) for i in combins]
for c in combins_list:
if all_exist(a_list, c) == True:
print c
output:
['A', 'A', 'A', 'B', 'C']
['A', 'A', 'B', 'B', 'C']
['A', 'A', 'B', 'C', 'C']
['A', 'B', 'B', 'B', 'C']
['A', 'B', 'B', 'C', 'C']
['A', 'B', 'C', 'C', 'C']
#doyz. I think this is may be what you are looking for :
From a list abc = ['A','B','C'], you want to obtain its various combinations with replacement. Python has built-in itertools to do this.
import itertools
abc = ['A', 'B', 'C'];
combins = itertools.combinations_with_replacement(abc, 5);
combins_list = [list(i) for i in combins];
print(combins_list[0:10]);
This is the first 10 combinations with replacement :
[['A', 'A', 'A', 'A', 'A'], ['A', 'A', 'A', 'A', 'B'], ['A', 'A', 'A', 'A', 'C'], \
['A', 'A', 'A', 'B', 'B'], ['A', 'A', 'A', 'B', 'C'], ['A', 'A', 'A', 'C', 'C'], \
['A', 'A', 'B', 'B', 'B'], ['A', 'A', 'B', 'B', 'C'], ['A', 'A', 'B', 'C', 'C'], ['A', 'A', 'C', 'C', 'C']]
If you want to include all elements in abc, here is one way, that also includes the permutations :
import itertools
abc = ['A', 'B', 'C'];
combins = itertools.combinations_with_replacement(abc, 5);
combins_list = list(combins);
combins_all =[];
for i in combins_list:
if len(set(i))==len(abc):
combins_all.append(i);
print(combins_all);
include_permutations=[];
for i in combins_all:
permut = list(itertools.permutations(i));
include_permutations.append(permut);
print(include_permutations);
Is this okay?
*Note : itertools.combinations_woth_replacement and itertools.permutations do not result in a list, or tuple, but a different object itself, so you can't treat it as those.
for the following code, how I can write into one line using lambda function or using python list comprehension?
def f():
lst=[]
for i in range(1, 101):
if i < 50:
lst.append('A')
else:
lst.append('B')
return lst
You can use a ternary conditional in a list comprehension:
lst = ['A' if i < 50 else 'B' for i in range(1, 101)]
Note that your function outputs 49 'A's and 51 'B's. I'm not sure if that's intentional.
The easiest way to get 50/50 would be :
['A'] * 50 + ['B'] * 50
If you want to define a lambda:
>>> a_or_b = lambda x: 'AB'[x>50]
>>> [a_or_b(x) for x in range(1,101)]
['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B']
As a one-liner :
['AB'[x>50] for x in range(1,101)]
or
['AB'[x>=50] for x in range(100)]
Those comprehensions use the fact that False is 0 and True is 1, and that 'AB'[0] is 'A' and 'AB'[1]is'B'`.
The code, mirroring yours, would be like this:
def f():
return ['A' if i < 50 else 'B' for i in range(1,101)]
I have an issue and I can't for the life of me get anything to return past ()
exam_solution = ['B', 'D', 'A', 'A', 'C', 'A', 'B', 'A', 'C', 'D', 'B', 'C',\
'D', 'A', 'D', 'C', 'C', 'B', 'D', 'A']
student_answers = ['B', 'D', 'B', 'A', 'C', 'A', 'A', 'A', 'C', 'D', 'B', 'C',\
'D', 'B', 'D', 'C', 'C', 'B', 'D', 'A']
I need to compare the 2 lists and append the differences into questions_missed = []
I haven't found anything remotely close to working. Any help would be appreciated
edit: In python been stroking out over it all day.
use python list comprehensions to check list diff:
print [(index, i, j) for index, (i, j) in enumerate(zip(exam_solution, student_answers)) if i != j]
[(2, 'A', 'B'), (6, 'B', 'A'), (13, 'A', 'B')]
You can modify this solution to fit your needs:
exam_solution = ['B', 'D', 'A', 'A', 'C', 'A', 'B', 'A', 'C', 'D', 'B', 'C', 'D', 'A', 'D', 'C', 'C', 'B', 'D', 'A']
student_answers = ['B', 'D', 'B', 'A', 'C', 'A', 'A', 'A', 'C', 'D', 'B', 'C', 'D', 'B', 'D', 'C', 'C', 'B', 'D', 'A']
results = []
correct = 0
incorrect = 0
index = 0
while index < len(student_answers):
if student_answers[index] == exam_solution[index]:
results.append(True)
correct += 1
else:
results.append(False)
incorrect += 1
index += 1
print("You answered " + correct + " questions correctly and " + incorrect + " questions incorrectly.")
Using list comprehensions:
[x for i, x in enumerate(exam_solution) if exam_solution[i] != student_answers[i] ]
['A', 'B', 'A']
Assuming you want an output in common English like this -
Question 3 A != B
Question 7 B != A
Question 14 A != B
You could try -
from array import *
exam_solution = ['B', 'D', 'A', 'A', 'C', 'A', 'B', 'A', 'C', 'D', 'B', 'C',\
'D', 'A', 'D', 'C', 'C', 'B', 'D', 'A']
student_answers = ['B', 'D', 'B', 'A', 'C', 'A', 'A', 'A', 'C', 'D', 'B', 'C',\
'D', 'B', 'D', 'C', 'C', 'B', 'D', 'A']
questions_missed = []
count = 0
for answer in exam_solution:
if (answer != student_answers[count]):
questions_missed.append(count)
count = count + 1
for question in questions_missed:
print str.format("Question {0} {1} != {2}", question+1,
exam_solution[question], student_answers[question]);
Using the KISS design principle, that's how I'd do it:
exam_solution = ['B', 'D', 'A', 'A', 'C', 'A', 'B', 'A', 'C', 'D', 'B', 'C',\
'D', 'A', 'D', 'C', 'C', 'B', 'D', 'A']
student_answers = ['B', 'D', 'B', 'A', 'C', 'A', 'A', 'A', 'C', 'D', 'B', 'C',\
'D', 'B', 'D', 'C', 'C', 'B', 'D', 'A']
questions_missed = []
for index in range(len(exam_solution)):
# this assumes exam_solution and student_answers have the same size!
if exam_solution[index] != student_answers[index]:
questions_missed.append(index)
print (questions_missed)
And the output is:
[2, 6, 13]
L = [(a, b) for a, b in zip(exam_solution, student_answers) if a != b]
print(L)
Mybe you can use zip function.
The output is:
[('A', 'B'), ('B', 'A'), ('A', 'B')]
Solution (use set):
>>> def result(solution, answers):
... return set(str(n)+s for n, s in enumerate(solution)) - \
... set(str(n)+r for n, r in enumerate(answers))
...
>>> result(exam_solution, student_answers)
... set(['6B', '13A', '2A'])
>>>
The result are wrong responses (you can convert to list list(result(student_answers)).
I have a list that contains multiple repeated items. I'm trying to sort the list by giving items with the most repetitions priority.
So it would turn this
['a', 'b', 'c', 'a', 'b', 'a', 'd']
into this
['a', 'a', 'a', 'b', 'b', 'c', 'd']
>>> from collections import Counter
>>> [k for k,v in Counter(['a', 'b', 'c', 'a', 'b', 'a', 'd']).most_common() for i in xrange(v)]
['a', 'a', 'a', 'b', 'b', 'c', 'd']
This is possibly easier to follow
>>> counter = Counter(['a', 'b', 'c', 'a', 'b', 'a', 'd'])
>>> sorted(counter.elements(), key=counter.get, reverse=True)
['a', 'a', 'a', 'b', 'b', 'c', 'd']
d = {}
for a in l:
d[a] += d.setdefault(a,0)
l.sort(key = lambda k: (d[k],k), reverse = True)
[v for (v, c) in sorted(((x, list(y)) for (x, y) in
itertools.groupby(sorted(['a', 'b', 'c', 'a', 'b', 'a', 'd']))),
key=lambda x: len(x[1]), reverse=True) for z in c]
EDIT:
Now with sum()!
sum((c for (v, c) in sorted(((x, list(y)) for (x, y) in
itertools.groupby(sorted(['a', 'b', 'c', 'a', 'b', 'a', 'd']))),
key=lambda x: len(x[1]), reverse=True)), [])
l = ['a', 'b', 'c', 'a', 'b', 'a', 'd']
sorted_list = [item for item in sorted(l, key=lambda x: l.count(x), reverse=True)]
While this is a simple solution, mind the complexity of counting every element when using large lists.