python: locate elements in sublists - python

given these sublists
lst=[['a', 'b', 'c', 'd', 'e'], ['f', 'g', 'h']]
I am trying to find the location of its elements,
for instance, the letter 'a' is located at 0,0
but this line
print(lst.index('a'))
instead produces the following error:
ValueError: 'a' is not in list

if your list have depth=2, you can use this:
lst=[['a', 'b', 'c', 'd', 'e'], ['f', 'g', 'h']]
def fnd_idx(char, lst):
for x in range(len(lst)):
try:
idx = lst[x].index(char)
return [x,idx]
except ValueError:
pass
return None
Output:
>>> print(fnd_idx('a', lst))
[0, 0]
>>> print(fnd_idx('g', lst))
[1, 1]
>>> print(fnd_idx('z', lst))
None

You can use list comprehension:
>>> lst=[['a', 'b', 'a', 'd', 'a'], ['f', 'g', 'a'], ['a','a','b']]
>>> [(i,j) for i in range(len(lst)) for j in range(len(lst[i])) if lst[i][j]=='a']
[(0, 0), (0, 2), (0, 4), (1, 2), (2, 0), (2, 1)]

Try this function (just one line of code!):
def idx(lst, el):
return next(((i, sublst.index(el))
for i, sublst in enumerate(lst)
if el in sublst),
None)
So for example:
>>> idx(lst, 'a')
(0, 0)
>>> idx(lst, 'c')
(0, 2)

lst=[['a', 'b', 'c', 'd', 'c'], ['f', 'g', 'h']]
searchvalue = 'f'
counter = 0
for index in lst:
if searchvalue in index:
print(counter, index.index(searchvalue))
counter+=1

If 'a' can appear in multiple sublists, and you want the index in each sublist:
def GetIndexes(lst, val):
pos = []
for sublist in lst:
try:
idx = sublist.index(val)
pos.append(idx)
except:
pos.append(None)
return pos
In your example : [0, None]
Meaning: In sublist 0, the first 'a' is at the index 0. In sublist 1, there is no 'a'.

you can do this with numpy, the benefit is you don't have to hardcode anything for the size of nested lists. you can have hundreds or 3 and this will work!
lst=[['a', 'b', 'c', 'd', 'e'], ['f', 'g', 'h']]
arr = np.array(lst, dtype=object)
for x in arr:
try:
print (x.index('a'), x)
except:
pass

Related

Removing duplicate characters from a list in Python where the pattern repeats

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

Make a list based on conditions in python to create a unique list

I have two lists:
a= [0,0,0,1,1,1,3,3,3]
b= ['a','b','c','d','e','f','g','h','i']
output = [['a','b','c'],['d','e','f'],['g','h','i']]
a and b are list of same length.
I need an output array by in such a way that whenever the value in list - a changes from 0 to 1 or from 1 to 3, A new list should be made in the output list.
can someone please help.
Use groupby:
from itertools import groupby
from operator import itemgetter
a = [0, 0, 0, 1, 1, 1, 3, 3, 3]
b = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
output = [list(map(itemgetter(1), group)) for _, group in groupby(zip(a, b), key=itemgetter(0))]
print(output)
Output
[['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]
A simpler method without using any imports by utilizing dictionary:
a= [0,0,0,1,1,1,3,3,3]
b= ['a','b','c','d','e','f','g','h','i']
d = {e: [] for e in set(a)} # Create a dictionary for each of a's unique key
[d[e].append(b[i]) for i, e in enumerate(a)] # put stuff into lists by index
lofl = list(d.values())
>>> lofl
[['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]
Using groupby, you could do:
from itertools import groupby
a= [0,0,0,1,1,1,3,3,3]
b= ['a','b','c','d','e','f','g','h','i']
iter_b = iter(b)
output = [[next(iter_b) for _ in group] for key, group in groupby(a)]
print(output)
# [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]
groupby yields successive groups of identical values of a. For each group, we create a list containing as many of the next elements of b as there are values in the group.
As you added tag algorithm , I believe you want a solution without so many magic.
>>> def merge_lists(A, B):
... output = []
... sub_list = []
... current = A[0]
... for i in range(len(A)):
... if A[i] == current:
... sub_list.append(B[i])
... else:
... output.append(sub_list)
... sub_list = []
... sub_list.append(B[i])
... current = A[i]
... output.append(sub_list)
... return output
...
>>> a= [0,0,0,1,1,1,3,3,3]
>>> b= ['a','b','c','d','e','f','g','h','i']
>>> merge_list(a, b)
[['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]

Adding an index to a list of a lists in python

I have a list of lists like this:-
x=[['A','B','C','D'],['E','F','G','H']]
I am trying to add an index to the list like this:-
y=[[0,'A','B','C','D'],[1,'E','F','G','H']]
Is there any way to achieve this?
y = [[i]+a for i,a in enumerate(x)]
Use enumerate and insert:
x = [['A','B','C','D'],['E','F','G','H']]
y = []
for index, li in enumerate(x):
li_copy = li[:]
li_copy.insert(0, index)
y.append(li_copy)
print(y)
# [[0, 'A', 'B', 'C', 'D'], [1, 'E', 'F', 'G', 'H']]
Or if you don't mind overwriting x:
x = [['A','B','C','D'],['E','F','G','H']]
for index, li in enumerate(x):
li.insert(0, index)
print(x)
# [[0, 'A', 'B', 'C', 'D'], [1, 'E', 'F', 'G', 'H']]
if you are looking for a simple function that achieves this try the following:
def add_index(itemList):
i = 0
setOfLists = []
for x in itemList:
set_of_lists.append([i] + x)
i +=1
return setOfLists
Could also use collections.deqeue for this:
from collections import deque
lst = [['A','B','C','D'],['E','F','G','H']]
result = []
for i, l in enumerate(lst):
q = deque(l)
q.appendleft(i)
result.append(list(q))
print(result)
Which Outputs:
[[0, 'A', 'B', 'C', 'D'], [1, 'E', 'F', 'G', 'H']]

Multiplying strings in a list by numbers from another list, element by element

I have two lists, ['A', 'B', 'C', 'D'] and [1, 2, 3, 4]. Both lists will always have the same number of items. I need to multiply each string by its number, so the final product I am looking for is:
['A', 'B', 'B', 'C', 'C', 'C', 'D', 'D', 'D', 'D']
Nested list comprehension works too:
>>> l1 = ['A', 'B', 'C', 'D']
>>> l2 = [1, 2, 3, 4]
>>> [c for c, i in zip(l1, l2) for _ in range(i)]
['A', 'B', 'B', 'C', 'C', 'C', 'D', 'D', 'D', 'D']
In above zip returns (char, count) tuples:
>>> t = list(zip(l1, l2))
>>> t
[('A', 1), ('B', 2), ('C', 3), ('D', 4)]
Then for every tuple the second for loop is executed count times to add the character to the result:
>>> [char for char, count in t for _ in range(count)]
['A', 'B', 'B', 'C', 'C', 'C', 'D', 'D', 'D', 'D']
I would use itertools.repeat for a nice, efficient implementation:
>>> letters = ['A', 'B', 'C', 'D']
>>> numbers = [1, 2, 3, 4]
>>> import itertools
>>> result = []
>>> for letter, number in zip(letters, numbers):
... result.extend(itertools.repeat(letter, number))
...
>>> result
['A', 'B', 'B', 'C', 'C', 'C', 'D', 'D', 'D', 'D']
>>>
I also think it is quite readable.
The code is pretty straight forward, see inline comments
l1 = ['A', 'B', 'C', 'D']
l2 = [1, 2, 3, 4]
res = []
for i, x in enumerate(l1): # by enumerating you get both the item and its index
res += x * l2[i] # add the next item to the result list
print res
OUTPUT
['A', 'B', 'B', 'C', 'C', 'C', 'D', 'D', 'D', 'D']
You use zip() to do it like this way:
a = ['A', 'B', 'C', 'D']
b = [1, 2, 3, 4]
final = []
for k,v in zip(a,b):
final += [k for _ in range(v)]
print(final)
Output:
>>> ['A', 'B', 'B', 'C', 'C', 'C', 'D', 'D', 'D', 'D']
Or you can do it, too, using zip() and list comprehension:
a = ['A', 'B', 'C', 'D']
b = [1, 2, 3, 4]
final = [k for k,v in zip(a,b) for _ in range(v)]
print(final)
Output:
>>> ['A', 'B', 'B', 'C', 'C', 'C', 'D', 'D', 'D', 'D']
You can use NumPy and then convert the NumPy array to a list:
letters = ['A', 'B', 'C', 'D']
times = [1, 2, 3, 4]
np.repeat(letters, times).tolist()
#output
['A', 'B', 'B', 'C', 'C', 'C', 'D', 'D', 'D', 'D']

In Python, how do I index a list with another list?

I would like to index a list with another list like this
L = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
Idx = [0, 3, 7]
T = L[ Idx ]
and T should end up being a list containing ['a', 'd', 'h'].
Is there a better way than
T = []
for i in Idx:
T.append(L[i])
print T
# Gives result ['a', 'd', 'h']
T = [L[i] for i in Idx]
If you are using numpy, you can perform extended slicing like that:
>>> import numpy
>>> a=numpy.array(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
>>> Idx = [0, 3, 7]
>>> a[Idx]
array(['a', 'd', 'h'],
dtype='|S1')
...and is probably much faster (if performance is enough of a concern to to bother with the numpy import)
T = map(lambda i: L[i], Idx)
A functional approach:
a = [1,"A", 34, -123, "Hello", 12]
b = [0, 2, 5]
from operator import itemgetter
print(list(itemgetter(*b)(a)))
[1, 34, 12]
I wasn't happy with any of these approaches, so I came up with a Flexlist class that allows for flexible indexing, either by integer, slice or index-list:
class Flexlist(list):
def __getitem__(self, keys):
if isinstance(keys, (int, slice)): return list.__getitem__(self, keys)
return [self[k] for k in keys]
Which, for your example, you would use as:
L = Flexlist(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
Idx = [0, 3, 7]
T = L[ Idx ]
print(T) # ['a', 'd', 'h']
You could also use the __getitem__ method combined with map like the following:
L = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
Idx = [0, 3, 7]
res = list(map(L.__getitem__, Idx))
print(res)
# ['a', 'd', 'h']
L= {'a':'a','d':'d', 'h':'h'}
index= ['a','d','h']
for keys in index:
print(L[keys])
I would use a Dict add desired keys to index
My problem: Find indexes of list.
L = makelist() # Returns a list of different objects
La = np.array(L, dtype = object) # add dtype!
for c in chunks:
L_ = La[c] # Since La is array, this works.

Categories