Python - For Loop - Print only if the above line is equal - python

I've the following code:
characters = ['a', 'b', 'b', 'c','d', 'b']
for i in characters:
if i[0] == i[-1]:
print(i)
Basically I only want to extract the characters that are equal from the line above. For example, in my case I only want to extract the b from 1 and 2 position.
How can I do that?
Thanks!

a = ['a', 'b', 'b', 'c', 'd', 'b']
b = ['a', 'b', 'b', 'c', 'd', 'b', 'd']
import collections
print([item for item, count in collections.Counter(a).items() if count > 1])
print([item for item, count in collections.Counter(b).items() if count > 1])
output
['b']
['b', 'd']

Without iterating multiple times over the same list.
characters = ['a', 'b', 'b', 'c','d', 'b']
last_char = None
output = []
for char in characters:
if char == last_char:
output.append(char)
last_char = char
print(output)

To extract the characters form the list which matches only the last char from list you can do the following:
characters = ['a', 'b', 'b', 'c','d', 'b']
for i in range(0, len(characters) - 1):
if characters[i] == characters[-1]:
print(characters[i])
In you snippet i when you are looping is the individual chars from your list, and it looks you were trying to access last, and first item from the list.

equal = [a for a in characters[0:-1] if a == characters[-1]]
Unless you also want the last character which will always be equal to itself, then do:
equal = [a for a in characters if a == characters[-1]]

little modification in your code
characters = ['a', 'b', 'b', 'c','d', 'b']
ch= (characters[-1])
for i in characters:
if i == ch:
print(i

Related

How to generate combination of characters in a string at a particular position?

I have a string list :
li = ['a', 'b', 'c', 'd']
Using the following code in Python, I generated all the possible combination of characters for list li and got a result of 256 strings.
from itertools import product
li = ['a', 'b', 'c', 'd']
for comb in product(li, repeat=4):
print(''.join(comb))
Say for example, I know the character of the second and fourth position of the string in the list li which is 'b' and 'c'.
So the result will be a set of only 16 strings which is :
abac
abbc
abcc
abdc
bbac
bbbc
bbcc
bbdc
cbac
cbbc
cbcc
cbdc
dbac
dbbc
dbcc
dbdc
How to get this result? Is there a Pythonic way to achieve this?
Thanks.
Edit : My desired size of list li is a to z and the value for repeat is 13. When I tried the above code, compiler throwed memory error!
Use list comprehension:
from itertools import product
li = ['a', 'b', 'c', 'd']
combs = [list(x) for x in product(li, repeat=4)]
selected_combs = [comb for comb in combs if (comb[1] == 'b' and comb[3] == 'c')]
print(["".join(comb) for comb in selected_combs])
# ['abac', 'abbc', 'abcc', 'abdc', 'bbac', 'bbbc', 'bbcc', 'bbdc', 'cbac', 'cbbc', 'cbcc', 'cbdc', 'dbac', 'dbbc', 'dbcc', 'dbdc']
To save memory in case you do not need all the combinations combs, you can simply do:
li = ['a', 'b', 'c', 'd']
selected_combs = [comb for comb in product(li, repeat=4) if (comb[1] == 'b' and comb[3] == 'c')]
print(["".join(comb) for comb in selected_combs])
def permute(s):
out = []
if len(s) == 1:
return s
else:
for i,let in enumerate(s):
for perm in permute(s[:i] + s[i+1:]):
out += [let + perm]
return out
per=permute(['a', 'b', 'c', 'd'])
print(per)
Do you want this?

Is there better way to check value changed in sequence?

I have a list like below:
list = ['A', 'A', 'B', 'A', 'B', 'A', 'B']
And, I want to count the number of the first value (in case above, 'A') consecutively before the other values ('B') come.
So I wrote a code like:
history = list[0]
number_A = 0
number_B = 0
for i in list:
if history != i:
break
if i == 'A':
number_A += 1
history = 'A'
else:
number_B += 1
history = 'B'
However, I think this is very untidy.
Is there any more simple way to do this process?
Thank you for reading.
Using groupby with the default key function, you can count the number of items in the first grouper:
from itertools import groupby
def count_first(lst):
if not lst:
return 0
_, grouper = next(groupby(lst))
return sum(1 for _ in grouper)
print(count_first(['A', 'A', 'B', 'A', 'B', 'A', 'B']))
# 2
There is no reason for the "else" clause, you are not going to count 'B's since you are going to break before you get there.
lst = ['A', 'A', 'B', 'A', 'B', 'A', 'B']
count = 0
for i in lst:
if i != lst[0]:
break
count += 1
print("list starts with %d of %s's" % (count, lst[0]))
You could use takewhile:
from itertools import takewhile
my_list = ['A', 'A', 'B', 'A', 'B', 'A', 'B']
res = takewhile(lambda x: x == my_list[0], my_list)
print(len(list(res)))
OUT: 2
I renamed your list to lst in order to not override the builtin name list.
>>> lst = ['A', 'A', 'B', 'A', 'B', 'A', 'B']
>>> string = ''.join(lst)
>>> len(string) - len(string.lstrip('A'))
2

How to get only lowercase strings from a list using list comprehension

The question asked:
Use list comprehensions to generate a list with only the lowercase letters in my_list. Print the result list.
['a', 'A', 'b', 'B', 'c', 'C', 'd', 'D']
My code:
my_list = ['a', 'A', 'b', 'B', 'c', 'C', 'd', 'D']
hi = ([ char for char in range(len(my_list)) if char%2 == 0])
print(hi)
I tried it out, but got integers as answers and not the strings I wanted.
Note: several answers here assume that what you want is to select the values in the list that are lowercase. This answer assumes that that was an example and that the thing you're trying to do is to select the values in the list that occur at every other list index. (This seems to me to be the correct interpretation, because that's what the implementation in the question appears to be trying to do.) I'm not sure who misunderstood the question here, but since the question can be interpreted multiple ways, I think the question is probably at fault here. Until the question is clarified, I think it should be placed on hold.
The simplest and fastest way to do this is with a slice:
print(my_list[::2]) # Slice the whole list, with step=2
To replicate the logic you're describing, where you want to take the values with indexes that are modulo 2, then you need to generate both the indexes and the values for your list in the comprehension, and use one for the filtering and the other for the result:
hi = [ch for ix, ch in enumerate(my_list) if ix % 2 == 0]
Python strings have islower method. Also, you can directly iterate over the list, no need to check its length or the parity of the indexes.
my_list = ['a', 'A', 'b', 'B', 'c', 'C', 'd', 'D']
hi = [char for char in my_list if char.islower()]
print(hi)
# ['a', 'b', 'c', d']
Your list comprehension:
[char for char in range(len(my_list)) if char%2 == 0]
Will produce integers instead of characters. This is because range(len(my_list)) gives you indices. You instead need to get the characters.
This can be done using enumerate():
[char for i, char in enumerate(my_list) if i % 2 == 0]
Or a less pythonic approach, using just indexing my_list:
[my_list[i] for i in range(len(my_list)) if i % 2 == 0]
You can also just filter out the lowercase letters with str.islower():
[char for char in my_list if char.islower()]
Which avoids having to use indices altogether.
You can use list comprehension as following where you iterate over your individual elements and check if it is a lower case using .islower()
my_list = ['a', 'A', 'b', 'B', 'c', 'C', 'd', 'D']
lower = [i for i in my_list if i.islower()]
# ['a', 'b', 'c', 'd']
my_list = ['a', 'A', 'b', 'B', 'c', 'C', 'd', 'D']
res = [ char for char in my_list if ord(char)>=97]
using islower() function
l = ['a', 'A', 'b', 'B', 'c', 'C', 'd', 'D']
result = [el for el in l if el.islower()]
To add a range(len(my_list)) that create the following range(0, 8)
and char, in this case, is an integer and you create a list of integers.
To generate a list with only the lowercase letters use 'islower' method
hi = ([ char for char in my_list if char.islower()])

Python: Keep first occurrence of an item in a list

How can I remove all occurrences of a specific value in a list except for the first occurrence?
E.g. I have a list:
letters = ['a', 'b', 'c', 'c', 'c', 'd', 'c', 'a', 'a', 'c']
And I need a function that looks something like this:
preserve_first(letters, 'c')
And returns this:
['a', 'b', 'c', 'd', 'a', 'a']
Removing all but the first occurrence of the given value while otherwise preserving the order. If there is a way to do this with a pandas.Series that would be even better.
You want to remove duplicates of 'c' only. So you want to filter where the series is either not duplicated at all or it isn't equal to 'c'. I like to use pd.Series.ne in place of pd.Series != because the reduction in wrapping parenthesis adds to readability (my opinion).
s = pd.Series(letters)
s[s.ne('c') | ~s.duplicated()]
0 a
1 b
2 c
5 d
7 a
8 a
dtype: object
To do exactly what was asked for.
def preserve_first(letters, letter):
s = pd.Series(letters)
return s[s.ne(letter) | ~s.duplicated()].tolist()
preserve_first(letters, 'c')
['a', 'b', 'c', 'd', 'a', 'a']
A general Python solution:
def keep_first(iterable, value):
it = iter(iterable)
for val in it:
yield val
if val == value:
yield from (el for el in it if el != value)
This yields all items up to and including the first value if found, then yields the rest of the iterable filtering out items matching the value.
You can try this using generators:
def conserve_first(l, s):
last_seen = False
for i in l:
if i == s and not last_seen:
last_seen = True
yield i
elif i != s:
yield i
letters = ['a', 'b', 'c', 'c', 'c', 'd', 'c', 'a', 'a', 'c']
print(list(conserve_first(letters, "c")))
Output:
['a', 'b', 'c', 'd', 'a', 'a']
Late to the party, but
letters = ['a', 'b', 'c', 'c', 'c', 'd', 'c', 'a', 'a', 'c']
def preserve_first(data, letter):
new = []
count = 0
for i in data:
if i not in new:
if i == letter and count == 0:
new.append(i)
count+=1
elif i == letter and count == 1:
continue
else:
new.append(i)
else:
if i == letter and count == 1:
continue
else:
new.append(i)
l = preserve_first(letters, "c")
You can use a list filter and slices:
def preserve_first(letters, elem):
if elem in letters:
index = letters.index(elem)
return letters[:index + 1] + filter(lambda a: a != 'c', letters[index + 1:])
Doesn't use pandas but this is a simple algorithm to do the job.
def preserve_firsts(letters, target):
firsts = []
seen = False
for letter in letters:
if letter == target:
if not seen:
firsts.append(letter)
seen = True
else:
firsts.append(letter)
return firsts
> letters = ['a', 'b', 'c', 'c', 'c', 'd', 'c', 'a', 'a']
> preserve_firsts(letters, 'c')
['a', 'b', 'c', 'd', 'a', 'a']
Simplest solution I could come up with.
letters = ['a', 'b', 'c', 'c', 'c', 'd', 'c', 'a', 'a', 'c']
key = 'c'
def preserve_first(letters, key):
first_occurrence = letters.index(key)
return [item for i, item in enumerate(letters) if i == first_occurrence or item != key]

Python 3 sort list -> all entries starting with lower case first

l1 = ['B','c','aA','b','Aa','C','A','a']
the result should be
['a','aA','b','c','A','Aa','B','C']
so same as l1.sort() but beginning with all words that start with lower case.
Try this:
>>> l = ['B', 'b','a','A', 'aA', 'Aa','C', 'c']
>>> sorted(l, key=str.swapcase)
['a', 'aA', 'b', 'c', 'A', 'Aa', 'B', 'C']
EDIT:
A one-liner using the list.sort method for those who prefer the imperative approach:
>>> l.sort(key=str.swapcase)
>>> print l
['a', 'aA', 'b', 'c', 'A', 'Aa', 'B', 'C']
Note:
The first approach leaves the state of l unchanged while the second one does change it.
Here is what you might be looking for:
li = ['a', 'A', 'b', 'B']
def sort_low_case_first(li):
li.sort() # will sort the list, uppercase first
index = 0 # where the list needs to be cuted off
for i, x in enumerate(li): # iterate over the list
if x[0].islower(): # if we uncounter a string starting with a lowercase
index = i # memorize where
break # stop searching
return li[index:]+li[:index] # return the end of the list, containing the sorted lower case starting strings, then the sorted uppercase starting strings
sorted_li = sort_low_case_first(li) # run the function
print(sorted_li) # check the result
>>> ['a', 'b', 'A', 'B']

Categories

Resources