I am monitoring a serial port that sends data that looks like this:
['','a','a','a','a','a','a','','b','b','b','b','b','b','b','b',
'','','c','c','c','c','c','c','','','','d','d','d','d','d','d','d','d',
'','','e','e','e','e','e','e','','','a','a','a','a','a','a',
'','','','b','b','b','b','b','b','b','b','b','','','c','c','c','c','c','c',
'','','','d','d','d','d','d','d','','','e','e','e','e','e','e',
'','','a','a','a','a','a','a','','b','b','b','b','b','b','b','b',
'','','c','c','c','c','c','c','','','','d','d','d','d','d','d','d','d',
'','','e','e','e','e','e','e','','','a','a','a','a','a','a',
'','','','b','b','b','b','b','b','b','b','b','','','c','c','c','c','c','c',
'','','','d','d','d','d','d','d','','','e','e','e','e','e','e','','']
I need to be able to convert this into:
['a','b','c','d','a','b','c','d','a','b','c','d','a','b','c','d']
So I'm removing duplicates and empty strings, but also retaining the number of times the pattern repeats itself.
I haven't been able to figure it out. Can someone help?
Here's a solution using a list comprehension and itertools.zip_longest: keep an element only if it's not an empty string, and not equal to the next element. You can use an iterator to skip the first element, to avoid the cost of slicing the list.
from itertools import zip_longest
def remove_consecutive_duplicates(lst):
ahead = iter(lst)
next(ahead)
return [ x for x, y in zip_longest(lst, ahead) if x and x != y ]
Usage:
>>> remove_consecutive_duplicates([1, 1, 2, 2, 3, 1, 3, 3, 3, 2])
[1, 2, 3, 1, 3, 2]
>>> remove_consecutive_duplicates(my_list)
['a', 'b', 'c', 'd', 'e', 'a', 'b', 'c', 'd', 'e', 'a', 'b', 'c', 'd',
'e', 'a', 'b', 'c', 'd', 'e']
I'm assuming either that there are no duplicates separated by empty strings (e.g. 'a', '', 'a'), or that you don't want to remove such duplicates. If this assumption is wrong, then you should filter out the empty strings first:
>>> example = ['a', '', 'a']
>>> remove_consecutive_duplicates([ x for x in example if x ])
['a']
You can loop over the list and add the appropriate contitions. For the response that you are expecting, you just need to whether previous character is not same as current character
current_sequence = ['','a','a','a','a','a','a','','b','b','b','b','b','b','b','b','','','c','c','c','c','c','c','','','','d','d','d','d','d','d','d','d','','','e','e','e','e','e','e','','','a','a','a','a','a','a','','','','b','b','b','b','b','b','b','b','b','','','c','c','c','c','c','c','','','','d','d','d','d','d','d','','','e','e','e','e','e','e','','','a','a','a','a','a','a','','b','b','b','b','b','b','b','b','','','c','c','c','c','c','c','','','','d','d','d','d','d','d','d','d','','','e','e','e','e','e','e','','','a','a','a','a','a','a','','','','b','b','b','b','b','b','b','b','b','','','c','c','c','c','c','c','','','','d','d','d','d','d','d','','','e','e','e','e','e','e','','']
sequence_list = []
for x in range(len(current_sequence)):
if current_sequence[x]:
if current_sequence[x] != current_sequence[x-1]:
sequence_list.append(current_sequence[x])
print(sequence_list)
You need something like that
li = ['','a','a','a','a','a','a','','b','b','b','b','b','b','b','b','','','c','c','c','c','c','c','','','','d','d','d','d','d','d','d','d','','','e','e','e','e','e','e','','','a','a','a','a','a','a','','','','b','b','b','b','b','b','b','b','b','','','c','c','c','c','c','c','','','','d','d','d','d','d','d','','','e','e','e','e','e','e','','','a','a','a','a','a','a','','b','b','b','b','b','b','b','b','','','c','c','c','c','c','c','','','','d','d','d','d','d','d','d','d','','','e','e','e','e','e','e','','','a','a','a','a','a','a','','','','b','b','b','b','b','b','b','b','b','','','c','c','c','c','c','c','','','','d','d','d','d','d','d','','','e','e','e','e','e','e','','']
new_li = []
e_ = ''
for e in li:
if len(e) > 0 and e_ != e:
new_li.append(e)
e_ = e
print(new_li)
Output
['a', 'b', 'c', 'd', 'e', 'a', 'b', 'c', 'd', 'e', 'a', 'b', 'c', 'd', 'e', 'a', 'b', 'c', 'd', 'e']
You can use itertools.groupby:
if your list is ll
ll = [i for i in ll if i]
out = []
for k, g in groupby(ll, key=lambda x: ord(x)):
out.append(chr(k))
print(out)
#prints ['a', 'b', 'c', 'd', 'e', 'a', 'b', 'c', 'd', 'e', ...
from itertools import groupby
from operator import itemgetter
# data <- your data
a = [k for k, v in groupby(data) if k] # approach 1
b = list(filter(bool, map(itemgetter(0), groupby(data)))) # approach 2
assert a == b
print(a)
Result:
['a', 'b', 'c', 'd', 'e', 'a', 'b', 'c', 'd', 'e', 'a', 'b', 'c', 'd', 'e', 'a', 'b', 'c', 'd', 'e']
using the set method you can remove the duplicates from the list
data = ['','a','a','a','a','a','a','','b','b','b','b','b','b','b','b',
'','','c','c','c','c','c','c','','','','d','d','d','d','d','d','d','d',
'','','e','e','e','e','e','e','','','a','a','a','a','a','a',
'','','','b','b','b','b','b','b','b','b','b','','','c','c','c','c','c','c',
'','','','d','d','d','d','d','d','','','e','e','e','e','e','e',
'','','a','a','a','a','a','a','','b','b','b','b','b','b','b','b',
'','','c','c','c','c','c','c','','','','d','d','d','d','d','d','d','d',
'','','e','e','e','e','e','e','','','a','a','a','a','a','a',
'','','','b','b','b','b','b','b','b','b','b','','','c','c','c','c','c','c',
'','','','d','d','d','d','d','d','','','e','e','e','e','e','e','','']
print(set(data))
I am trying to take a set of answers either 'A' 'B' 'C' or 'D' in a specific order such as a multiple choice test and have the user input his answers. After I would like it to create a third list and print out what was right and wrong. Here is what I have so far.
userAnswersList = []
correctAnswers = ['A', 'C', 'A', 'A', 'D', 'B', 'C', 'A', 'C', 'B', 'A', 'D', 'C', 'A', 'D', 'C', 'B', 'B', 'D', 'A']
while len(userAnswersList) <= 19:
userAnswers = input('Give me each answer total of 20 questions I\'ll let you know how many you missed.')
userAnswersList.append(userAnswers.upper())
correctedList = []
for i in userAnswersList:
if i in correctAnswers:
correctedList.append(i)
else:
correctedList.append('XX')
print(correctedList)
So my end result would be the corrected list with a 'X' in place where they missed the answer, If it is right it just puts the user input in that place.
So after the user input their 20 answers it would look like
['A', 'C', 'A', 'XX', 'D', 'B', 'C', 'XX', 'C', 'B', 'A', 'XX', 'C', 'A', 'D', 'XX', 'B', 'B', 'XX', 'A']
if they missed 5 questions in that order
EDIT
Thank you again for all your help I was able to solve my problems with your help and some great answers. I used Nicks solution as that is how we are learning it.
I will try out others just so I can get used to them.
Rather than using:
for i in userAnswersList:
you may find it easier to iterate through the array and check if the values are equal, such as:
for i in range(len(userAnswersList)):
if userAnswersList[i] == correctAnswers[i]:
correctedList.append(userAnswersList[i])
else:
correctedList.append('XX')
There is no question here, so I'll assume you're asking what's wrong with what you have.
The compare section uses the same variable i in both lists but even if it was different it wouldn't work.
You'll need something along the following lines:
for i in range(len(correctAnswers)):
correctedList.append(correctAnswers[i] if userAnswersList[i] == correctAnswers[i] else 'XX')
This can be done using Python's map method.
As explained in the help for map:
map(...)
map(function, sequence[, sequence, ...]) -> list
Return a list of the results of applying the function to the items of
the argument sequence(s). If more than one sequence is given, the
function is called with an argument list consisting of the corresponding
item of each sequence, substituting None for missing values when not all
sequences have the same length. If the function is None, return a list of
the items of the sequence (or a list of tuples if more than one sequence).
So in that case, you want to compare each item of your two equal lists, and apply a condition against them. The condition we will introduce will follow this logic:
if something in one list is not equal to the other, set 'XX', otherwise return the value.
So, we will introduce what is called a "lambda" function here to put that above condition. Here is documentation on what a lambda is: http://www.python-course.eu/lambda.php
lambda x, y: 'XX' if x != y else y
So, when we put it all together, we have this:
d = map(lambda x, y: 'XX' if x != y else y, userAnswersList, correctAnswers)
Demo:
correctAnswers = ['A', 'C', 'A', 'A', 'D', 'B', 'C', 'A', 'C', 'B', 'A', 'D', 'C', 'A', 'D', 'C', 'B', 'B', 'D', 'A']
userAnswersList = ['A', 'C', 'A', 'B', 'D', 'B', 'C', 'A', 'A', 'B', 'A', 'C', 'C', 'A', 'D', 'C', 'D', 'C', 'D', 'B']
Result:
['A', 'C', 'A', 'XX', 'D', 'B', 'C', 'A', 'XX', 'B', 'A', 'XX', 'C', 'A', 'D', 'C', 'XX', 'XX', 'D', 'XX']
You can zip the two lists together and check the elements at common indexes, you can get all the answers using a list comprehension replacing your while with range:
userAnswersList = [input('Give me each answer total of 20 questions I\'ll let you know how many you missed.').upper()
for _ in range(20)]
correctAnswers = ['A', 'C', 'A', 'A', 'D', 'B', 'C', 'A', 'C', 'B', 'A', 'D', 'C', 'A', 'D', 'C', 'B', 'B', 'D', 'A']
correctedList = ["XX" if u_a != c_a else u_a for u_a, c_a in zip(userAnswersList)]
If the corresponding elements from each list are the same we add the letter, if not we add "XX" to mark an incorrect answer.