Evaluating subset of a list using in operator - python

I have following test code.
a = ['a', 'b', 'c', 'd', 'e']
c = a * 3
b = a
but b in c returns False. b is a sub sequence of c and the list c contains b. So why is it returning false?
Thanks in advance.

b in c
Does not work because b looks like:
['a', 'b', 'c', 'd', 'e']
and c looks like:
['a', 'b', 'c', 'd', 'e', 'a', 'b', 'c', 'd', 'e', 'a', 'b', 'c', 'd', 'e']
In other words, b is not an element of the sequence. Instead, b is a subsequence. If you were to construct c as follows:
c = [a, a, a]
Then c would look like:
[['a', 'b', 'c', 'd', 'e'], ['a', 'b', 'c', 'd', 'e'], ['a', 'b', 'c', 'd', 'e']]
And "b in c" would return True.
Hope this helps.

If you had this code:
a = ['a', 'b', 'c', 'd', 'e']
c = [a] * 3
b = a
when you type b in c you would get True.
In this case
c = [a] * 3 (with [ ] around a)
would return:
[['a', 'b', 'c', 'd', 'e'], ['a', 'b', 'c', 'd', 'e'], ['a', 'b', 'c', 'd', 'e']]

Related

Iterating through a list for specific instances

I have the following code:
paths = [['E', 'D', 'A', 'B'], ['E', 'D', 'A', 'C', 'B'], ['E', 'D', 'B'], ['E', 'D', 'C', 'B'], ['E', 'B'], ['E', 'C', 'B']]
Now, the lists inside a list represent node paths from start to end which were made using Networkx, however that is some background information. My question is more specific.
I am trying to derive the lists that only have every letter from A-E, aka it would return only the list:
paths_desired = [['E', 'D', 'A', 'C', 'B']]
If I were to have another path:
paths = [['E', 'D', 'A', 'B'], ['E', 'D', 'A', 'C', 'B'], ['D', 'B', 'A','C','E'], ['A', 'D', 'C', 'B']]
It would return:
paths_desired = [['E', 'D', 'A', 'C', 'B'],['D', 'B', 'A', 'C', 'E']]
My idea is a for loop that iterates through each list:
for i in pathways:
counter = 0
for j in letters:
if j in i:
counter = counter + 1;
if counter == 5:
desired_paths.append(i)
print(desired_paths)
This works, however, I want to make the loop more specific, meaning I want only lists that have the following order: ['E','D','A','C','B'], even if all the letters are present in a different list, within the paths list.
Additionally, is there a way I can upgrade my for loop, so that I wouldn't count, rather check if the letters are in there, and not more than 1 of each letter? Meaning no multiple Es, no multiple D, etc.
You can use a use a set and .issubset() like this:
def pathways(letters, paths):
ret = []
letters = set(letters)
for path in paths:
if letters.issubset(path):
ret.append(path)
return ret
letters = ['A', 'B', 'C', 'D', 'E']
paths = [['E', 'D', 'A', 'B'], ['E', 'D', 'A', 'C', 'B'],
['D', 'B', 'A','C','E'], ['A', 'D', 'C', 'B']]
print(pathways(letters, paths)) # => [['E', 'D', 'A', 'C', 'B'], ['D', 'B', 'A', 'C', 'E']]
Also, as a comment by ShadowRanger pointed out, the pathways() function could be shortened using filter(). Like this:
def pathways(letters, paths):
return list(filter(set(letters).issubset, paths))
letters = ['A', 'B', 'C', 'D', 'E']
paths = [['E', 'D', 'A', 'B'], ['E', 'D', 'A', 'C', 'B'],
['D', 'B', 'A','C','E'], ['A', 'D', 'C', 'B']]
print(pathways(letters, paths))

python join strings in list of lists

I have a list of lists of individual litters,
however I I would like a list of lists of a string.
What I have:
[
['a', 'b', 'c', 'd', 'e'],
['b', 'c', 'd', 'e', 'a'],
['c', 'd', 'e', 'a', 'b'],
['d', 'e', 'a', 'b', 'c'],
['e', 'a', 'b', 'c', 'd']
]
What I need:
[
['a b c d e'],
['b c d e a'],
['c d e a b'],
['d e a b c'],
['e a b c d']
]
I guess below will work as you wish.
list = [
['a', 'b', 'c', 'd', 'e'],
['b', 'c', 'd', 'e', 'a'],
['c', 'd', 'e', 'a', 'b'],
['d', 'e', 'a', 'b', 'c'],
['e', 'a', 'b', 'c', 'd']
]
newList = [[' '.join(elem)] for elem in list]
print(newList)
List comprehension:
result = [[' '.join(inner)] for inner in outer_list]
You can also do it with this
array = [['a', 'b', 'c', 'd', 'e'], ['f', 'g', 'h', 'i', 'j']]
string = [' '.join(i).split(',') for i in array]
print(string)
You can also do with map,
list(map(lambda x:[' '.join(x)], lst))

How to reverse a part of a list?

I have the next list:
abclist = ['a', 'b', 'c', 'd', 'e']
With the above list I how to create the next one?
Reversed_part = ['c', 'b', 'a', 'd', 'e']
Only the first 3 items are reversed and the last two stay in the same order.
This is one way.
lst = ['a', 'b', 'c', 'd', 'e']
def partial_reverse(lst, start, end):
"""Indexing (start/end) inputs begins at 0 and are inclusive."""
return lst[:start] + lst[start:end+1][::-1] + lst[end+1:]
partial_reverse(lst, 0, 2) # ['c', 'b', 'a', 'd', 'e']
abclist = ['a', 'b', 'c', 'd', 'e']
quantityToReverse = 3
remainder = len(abclist) - quantityToReverse
reverseArray = list(reversed(abclist[:quantityToReverse]))+abclist[-remainder:]
print(reverseArray)
You can do it using a combination of reversed method & string slicing
Ex:
abclist = ['a', 'b', 'c', 'd', 'e']
print(list(reversed(abclist[:3]))+abclist[-2:])
Output:
['c', 'b', 'a', 'd', 'e']

Create combinations from a list and 3 ranges using itertools

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.

Comparing 2 lists and appending the differences into a 3rd

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)).

Categories

Resources