How can copy string in the list? - python

I have a list
list1=['a','b','c]
I wnat to copy every string in the list
like this
list2=['a','a','b','b','c','c']
list3=['a','a','a','b','b','b','c','c','c']
but when I use this code
list2=[x*2 for x in list1]
I get
list2=['aa','bb','cc]
How can I change my code to accomplish my result?

I would use itertools.chain along with itertools.repeat:
from itertools import chain, repeat
chars = ['a', 'b', 'c']
repeat_count = 3
list(chain.from_iterable(repeat(char, repeat_count) for char in chars))
Output:
['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c']

without using itertools, this could be done with nested list comprehension like below
list1=['a','b','c']
print([y for x in list1 for y in [x]*2])
# ['a', 'a', 'b', 'b', 'c', 'c']
print([y for x in list1 for y in [x]*3])
# ['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c']

You can use the second for loop with the function range():
lst = ['a', 'b', 'c']
[i for i in lst for _ in range(2)]
# ['a', 'a', 'b', 'b', 'c', 'c']

Related

How to efficiently split a list that has a certain periodicity, into multiple lists?

For example the original list:
['k','a','b','c','a','d','e','a','b','e','f','j','a','c','a','b']
We want to split the list into lists started with 'a' and ended with 'a', like the following:
['a','b','c','a']
['a','d','e','a']
['a','b','e','f','j','a']
['a','c','a']
The final ouput can also be a list of lists. I have tried a double for loop approach with 'a' as the condition, but this is inefficient and not pythonic.
One possible solution is using re (regex)
import re
l = ['k','a','b','c','a','d','e','a','b','e','f','j','a','c','a','b']
r = [list(f"a{_}a") for _ in re.findall("(?<=a)[^a]+(?=a)", "".join(l))]
print(r)
# [['a', 'b', 'c', 'a'], ['a', 'd', 'e', 'a'], ['a', 'b', 'e', 'f', 'j', 'a'], ['a', 'c', 'a']]
You can do this in one loop:
lst = ['k','a','b','c','a','d','e','a','b','e','f','j','a','c','a','b']
out = [[]]
for i in lst:
if i == 'a':
out[-1].append(i)
out.append([])
out[-1].append(i)
out = out[1:] if out[-1][-1] == 'a' else out[1:-1]
Also using numpy.split:
out = [ary.tolist() + ['a'] for ary in np.split(lst, np.where(np.array(lst) == 'a')[0])[1:-1]]
Output:
[['a', 'b', 'c', 'a'], ['a', 'd', 'e', 'a'], ['a', 'b', 'e', 'f', 'j', 'a'], ['a', 'c', 'a']]
Firstly you can store the indices of 'a' from the list.
oList = ['k','a','b','c','a','d','e','a','b','e','f','j','a','c','a','b']
idx_a = list()
for idx, char in enumerate(oList):
if char == 'a':
idx_a.append(idx)
Then for every consecutive indices you can get the sub-list and store it in a list
ans = [oList[idx_a[x]:idx_a[x + 1] + 1] for x in range(len(idx_a))]
You can also get more such lists if you take in-between indices also.
You can do this with a single iteration and a simple state machine:
original_list = list('kabcadeabefjacab')
multiple_lists = []
for c in original_list:
if multiple_lists:
multiple_lists[-1].append(c)
if c == 'a':
multiple_lists.append([c])
if multiple_lists[-1][-1] != 'a':
multiple_lists.pop()
print(multiple_lists)
[['a', 'b', 'c', 'a'], ['a', 'd', 'e', 'a'], ['a', 'b', 'e', 'f', 'j', 'a'], ['a', 'c', 'a']]
We can use str.split() to split the list once we str.join() it to a string, and then use a f-string to add back the stripped "a"s. Note that even if the list starts/ends with an "a", this the split list will have an empty string representing the substring before the split, so our unpacking logic that discards the first + last subsequences will still work as intended.
def split(data):
_, *subseqs, _ = "".join(data).split("a")
return [list(f"a{seq}a") for seq in subseqs]
Output:
>>> from pprint import pprint
>>> testdata = ['k','a','b','c','a','d','e','a','b','e','f','j','a','c','a','b']
>>> pprint(split(testdata))
[['a', 'b', 'c', 'a'],
['a', 'd', 'e', 'a'],
['a', 'b', 'e', 'f', 'j', 'a'],
['a', 'c', 'a']]

Append a value to list only if it has not occurred previously

I have a list of strings. I am trying to append the values to a new list but, only those values which are not consecutive.
like for example,
If i have a list like this,
['a', 'a', 'a', 'b', 'b', 'a']
I need output like
['a', 'b', 'a']
Use itertools.groupby
Ex:
from itertools import groupby
data = ['a', 'a', 'a', 'b', 'b', 'a']
print([k for k, _ in groupby(data)])
# --> ['a', 'b', 'a']
You can use zip_longest from itertools and compare with the next element in the list:
from itertools import zip_longest
a = ['a', 'a', 'a', 'b', 'b', 'a']
b = [i for i,j in zip_longest(a,a[1:]) if i!=j]
print(b)

Iterating over two lists A and B

I am trying to iterate over two lists A and B. Where the B is equal to A - A[i], where i = 1:
For E.g. listA = ['A', 'B', 'C', 'D'].
For first Item, 'A' in List A, I
want the List B to have ['B', 'C', 'D'] For second Item 'B' in List A,
I want the List B to have ['A', 'C', 'D']
What I have tried until now.
listA = ['A', 'B', 'C', 'D']
for term in listA:
listA.remove(term)
for item in listA:
print(listA)
If all you want is to print the sublists, it will be like:
for i in range(len(listA)):
print(listA[:i]+listA[i+1:])
Or,
for i in listA:
print(list(set(listA) - set(i)))
Try this,
>>> la = ['A', 'B', 'C', 'D']
>>> for i in la:
_temp = la.copy()
_temp.remove(i)
print(_temp)
Output:
['B', 'C', 'D']
['A', 'C', 'D']
['A', 'B', 'D']
['A', 'B', 'C']
*If you want to assign the print output to new variables, use a dictionary where the key will the name of list and value is printted output.
Is this what you want?
listA = ['A', 'B', 'C', 'D']
Bs = \
[listA[:idx] + listA[idx + 1:]
for idx
in range(len(listA))]
for B in Bs:
print(B)
Taking the above solutions a step further, you can store a reference to each of the resulting list in the corresponding variable using a dictionary comprehension:
keys_map = {x: [item for item in listA if item != x] for x in listA}
print(keys_map)
Output
{
'A': ['B', 'C', 'D'],
'B': ['A', 'C', 'D'],
'C': ['A', 'B', 'D'],
'D': ['A', 'B', 'C']
}
and access the desired key like so
keys_map.get('A')
# returns
['B', 'C', 'D']

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']

Find the same elements from two lists and print the elements from both lists

There are two lists:
k = ['a', 'a', 'b', 'b', 'c', 'c', 'd', 'e']
l = ['a', 'c', 'e']
I want to find the same elements from these two lists, that is:
['a', 'c', 'e']
then I want to print out the element we found, for example, 'a' from both lists, that is: ['a', 'a', 'a'].
The result I want is as follows:
['a', 'a', 'a', 'c', 'c', 'c', 'e', 'e']
I try to doing in this way:
c = []
for item_k in k:
for item_j in j:
if item_k== item_j:
c.append(item_k)
c.append(item_j)
However, the result is ['a', 'a', 'c', 'c', 'e', 'e']
Also in this way:
c=[]
for item_k in k:
if item_k in l:
c.append(item_k)
d=l.count(item_k)
c.append(item_k*d)
print c
But it do not works, can anybody tell me how to do it? really appreciate your help in advance
result = [x for x in sorted(k + l) if x in k and x in l]
print(result)
results:
['a', 'a', 'a', 'c', 'c', 'c', 'e', 'e']
Since you want to pick up elements from both lists, the most straight forward way is probably to iterate over both while checking the other one (this is highly optimizatiable if you depend on speed for doing this):
merged = []
for el in list1:
if el in list2:
merged.append(el)
for el in list2:
if el in list1:
merged.append(el)
.. if the order of the elements is important, you'll have to define an iteration order (in what order do you look at what element from what array?).
If the lists are sorted and you want the result to be sorted:
sorted([x for x in list1 if x in set(list2)] + [x for x in list2 if x in set(list1)] )
You can use set operations to intersect and then loop through, appending to a new list any that match the intersected list
k = ['a', 'a', 'b', 'b', 'c', 'c', 'd', 'e']
l = ['a', 'c', 'e']
common_list = list(set(k).intersection(set(l)))
all_results = []
for item in k:
if item in common_list:
all_results.append(item)
for item in l:
if item in common_list:
all_results.append(item)
print sorted(all_results)
output:
['a', 'a', 'a', 'c', 'c', 'c', 'e', 'e']
Here's a compact way. Readability might suffer a little, but what fun are comprehensions without a little deciphering?
import itertools
k = ['a', 'a', 'b', 'b', 'c', 'c', 'd', 'e']
l = ['a', 'c', 'e']
combined = [letter for letter in itertools.chain(k,l) if letter in l and letter in k]
Here is an implementation that matches your initial algorithm:
k = ['a', 'a', 'b', 'b', 'c', 'c', 'd', 'e']
l=['a', 'c', 'e']
c=[]
for x in l:
count = 0
for y in k:
if x == y:
count += 1
while count>=0:
c.append(x)
count = count -1
print c

Categories

Resources