using index() on multidimensional lists - python

For a one dimensional list, the index of an item is found as follows:
a_list = ['a', 'b', 'new', 'mpilgrim', 'new']
a_list.index('mpilgrim')
What is the equivalent for a 2 or n dimensional list?
Edit: I have added an example to clarify:
If I have a 3 dimensional list as follows
b_list = [
[1,2],
[3,4],
[5,6],
[7,8]
],
[
[5,2],
[3,7],
[6,6],
[7,9]
]
Now lets say I want to identify a certain value in this list. If I know the index of the 1st and 2nd dimesion but don't know the zero-th index for the value I want, how do I go about finding the zero-th index?
Would it be something like:
target_value = 7
b_list[0].index(target_value)
With the output being an integer:
0

I don't know of an automatic way to do it, but if
a = [[1,2],[3,4],[5,6]]
and you want to find the location of 3, you can do:
x = [x for x in a if 3 in x][0]
print 'The index is (%d,%d)'%(a.index(x),x.index(3))
The output is:
The index is (1,0)

For two dimensional list; you can iterate over rows and using .index function for looking for item:
def find(l, elem):
for row, i in enumerate(l):
try:
column = i.index(elem)
except ValueError:
continue
return row, column
return -1
tl = [[1,2,3],[4,5,6],[7,8,9]]
print(find(tl, 6)) # (1,2)
print(find(tl, 1)) # (0,0)
print(find(tl, 9)) # (2,2)
print(find(tl, 12)) # -1

A multidimensional list is simply a list with more lists inside of it.
So its indices would be lists themselves.
a = [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
print a.index([2, 3, 4])
# prints 1

list_2d = [[1,2],[3,4],[5,6]]
element = 1
index_row = [list_2d.index(row) for row in list_2d if element in row]
index_column = [row.index(element) for row in list_2d if element in row]

For multidimensional arrays:
def find(needle,haystack):
if needle == haystack: return []
# Strings are iterable, too
if isinstance(haystack,str) and len(haystack)<=1: return None
try:
for i,e in enumerate(haystack):
r = find(needle,e)
if r is not None:
r.insert(0,i)
return r
except TypeError:
pass
return None
ml = [[1,2,3],[4,5,6],[7,8,9]]
print find(2,ml)
ml = [3,[[1,2,3],[4,5,6],[7,8,9]]]
print find(2,ml)
ml = [[["ab", "bc", "cde"]]]
print find("d",ml)
There should be a better way to avoid the try/except block, but I could not find one:
In Python, how do I determine if an object is iterable?

You can use the following sample method too:
data = [[1, 1,2],[12,4],[6]]
def m_array_index(arr, searchItem):
for i,x in enumerate(a):
for j,y in enumerate(x):
if y == searchItem:
return i,j
return -1,-1#not found
print m_array_index(data, 6)
Or with all occurrences(sure code could be optimized - modified to work with generators and so on - but here is just a sample):
occurrences = lambda arr, val: tuple((i,j) for i,x in enumerate(arr) for j,y in enumerate(x) if y == val) or ((-1,-1))
print occurrences(data, 1) # ((0, 0), (0, 1))
print occurrences(data, 12) # ((1, 0),)
print occurrences(data, 11) # (-1, -1)

For n-dimensional recursive search, you can try something like this:
from copy import copy
def scope(word, list, indexes = None):
result = []
if not indexes:
indexes = []
for index, item in enumerate(list):
try:
current_index = indexes + [index]
result.append(current_index + [item.index(word)])
except ValueError:
pass
if type(item[0]) == type([]):
indexes.append(index)
result.extend(scope(word, item, copy(indexes)))
return result
And the result is:
>>> d_list = [['a', 'b', 'new', 'mpilgrim', 'new'], [['a', 'b', 'new', 'mpilgrim', 'new'], ['b', 'd', 'new', 'mpilgrim', 'new']]]
>>> word = 'mpilgrim'
>>> result = scope(word, d_list)
[[0, 3], [1, 0, 3], [1, 1, 3]]
Probably there are better ways to do it, but that is the one I figured out without getting any library.
EDIT:
Actually, it was not perfect and one library must be added. It's copy. Now it's ok.

If you want to find the list that has an item, the simplest way to do it is:
i = 4
index = b_list[0].index( filter(lambda 1D_list: i in index , b_list[0]) )
Or if you know there are more than one matches for the item, then you can do:
i = 4
indexes = []
for match in filter(lambda 1D_list: i in list, b_list[0]):
indexes.append(b_list[0].index(match))
None of this will raise any errors but they'll only work if there is no subarray. Go here for information about the functionality of filter.

list1 = [10, 20, [300, 400, [5000, 6000, [1, 6000, 2]], 6000, 500], 30, 40]
print(f'Your list is {list1}')
print('---------------------------------------------------------')
index = []
index_result=['6000 index is list1']
def try_this(list1, index):
for x, element in enumerate(list1):
if element == 6000:
index.append(x)
index_result.append(index[:])
index.pop()
elif type(element) == list:
index.append(x)
try_this(element, index)
index.pop()
print(try_this(list1, index))
print(index_result)

Related

Checking if a list contains a certain sequence of items [duplicate]

I need to check if list1 is a sublist of list2 (True; if every integer in list2 that is common with list1 is in the same order of indexes as in list1)
def sublist(lst1,lst2):
for i in range(len(lst1)):
if lst1[i] not in lst2:
return False
for j in range(len(lst2)):
if (lst1[j] in lst2) and (lst2.index(lst1[i+1]) > lst2.index(lst1[i])):
return True
Can anybody help me... why isn't this working?
An easy way to check if all elements of a list are in other one is converting both to sets:
def sublist(lst1, lst2):
return set(lst1) <= set(lst2)
i need to check if list1 is a sublist to list2 (True; if every integer in list2 that is common with list1 is in the same order of indexes as in list1)
Your code isn't working because as soon as a list element in ls1 doesn't occur in ls2 it will return False immediately.
This creates two lists that contain only the common elements (but in their original order) and then returns True when they are the same:
def sublist(lst1, lst2):
ls1 = [element for element in lst1 if element in lst2]
ls2 = [element for element in lst2 if element in lst1]
return ls1 == ls2
edit: A memory-efficient variant:
def sublist(ls1, ls2):
'''
>>> sublist([], [1,2,3])
True
>>> sublist([1,2,3,4], [2,5,3])
True
>>> sublist([1,2,3,4], [0,3,2])
False
>>> sublist([1,2,3,4], [1,2,5,6,7,8,5,76,4,3])
False
'''
def get_all_in(one, another):
for element in one:
if element in another:
yield element
for x1, x2 in zip(get_all_in(ls1, ls2), get_all_in(ls2, ls1)):
if x1 != x2:
return False
return True
Another easy way is to use list comprehension
And use the built-in function all to verify that all items in list1 are contained in list2.
Example:
list1 = ['1','2']
list2 = ['1','2',3]
all(i in list2 for i in list1)
Another way that we do this is with collections.Counter. #L3viathan's second answer is the most efficient and fastest way to do it.
def sublist1(lst1, lst2):
ls1 = [element for element in lst1 if element in lst2]
ls2 = [element for element in lst2 if element in lst1]
return ls1 == ls2
def sublist2(lst1, lst2):
def get_all_in(one, another):
for element in one:
if element in another:
yield element
for x1, x2 in zip(get_all_in(lst1, lst2), get_all_in(lst2, lst1)):
if x1 != x2:
return False
return True
def sublist3(lst1, lst2):
from collections import Counter
c1 = Counter(lst1)
c2 = Counter(lst2)
for item, count in c1.items():
if count > c2[item]:
return False
return True
l1 = ["a", "b", "c", "c", "c", "d", "e"]
l2 = ["c", "a", "c", "b", "c", "c", "d", "d", "f", "e"]
s1 = lambda: sublist1(l1, l2)
s2 = lambda: sublist2(l1, l2)
s3 = lambda: sublist3(l1, l2)
from timeit import Timer
t1, t2, t3 = Timer(s1), Timer(s2), Timer(s3)
print(t1.timeit(number=10000)) # => 0.034193423241588035
print(t2.timeit(number=10000)) # => 0.012621842119714115
print(t3.timeit(number=10000)) # => 0.12714286673722477
His 2nd way is faster by an order of magnitude, but I wanted to mention the Counter variant because of its prevalence and usage outside of this scenario.
b = sublist and a = list then search b by splitting a in lengths of b
e.g.
>>> a = [2,4,3,5,7] , b = [4,3]
>>> b in [a[i:len(b)+i] for i in xrange(len(a))]
True
>>> a = [2,4,3,5,7] , b = [4,10]
>>> b in [a[i:len(b)+i] for i in xrange(len(a))]
False
Memory efficient solution based on M. Morgan's answer. Takes into consideration that in order to be a sublist, the sublist must be found in the same order in the super list.
Variable k keeps track of the length of matched characters. When this matches the length of our sublist we can return true.
Variable s keeps track of the starting value. I keep track of this so that a test case like sublist(["1", "1", "2"],["0", "1", "1", "1", "2", "1", "2"]) with extraneous repeats of the first entry don't affect the current index reset when unmatched. Once the starting value changes s becomes irrelevant so this case does not fire in the middle of a pattern.
def sublist(sublist, lst):
if not isinstance(sublist, list):
raise ValueError("sublist must be a list")
if not isinstance(lst, list):
raise ValueError("lst must be a list")
sublist_len = len(sublist)
k=0
s=None
if (sublist_len > len(lst)):
return False
elif (sublist_len == 0):
return True
for x in lst:
if x == sublist[k]:
if (k == 0): s = x
elif (x != s): s = None
k += 1
if k == sublist_len:
return True
elif k > 0 and sublist[k-1] != s:
k = 0
return False
what's wrong with the following:
def sublist(lst1, lst2):
return all([(x in lst2) for x in lst1])
will return true if for all items in lst1, each item exists in lst2
def sublist(l1,l2):
s1=" ".join(str(i) for i in l1)
s2=" ".join(str(i) for i in l2)
if s1 in s2:
return True
else:
return False
I found the above all found ['a','b','d'] to be a sublist of ['a','b','c','e','d'], which may not be true in spite of all of the elements of the sublist being present in the list. So to maintain the order and I came up with:
def sublist4(sublist,lst):
#Define an temp array to populate
sub_list=[]
comparable_sublist=[]
#Define two constants to iterate in the while loop
i=0
k=0
#Loop the length of lst
while i < len(lst):
#If the element is in the sublist append to temp array,
if k < len(sublist) and lst[i] == sublist[k]:
sub_list.append(lst[i])
#set a comparable array to the value of temp array
comparable_sublist = sub_list
k += 1
#If the comparable array is the same as the sublist, break
if len(comparable_sublist) == len(sublist):
break
#If the element is not in the sublist, reset temp array
else:
sub_list = []
i += 1
return comparable_sublist == sublist
Whilst this isn't very memory efficient, I find it works quite well with small lists.
def has_ordered_intersection(xs, ys):
common = {*xs} & {*ys}
return all(x == y for x, y in zip((x for x in xs if x in common),
(y for y in ys if y in common)))
This passes #L3viathan's doctest with fewer lines of code, using a similar strategy to the "memory-efficient variant", and with arguably greater overall efficiency.
>>> has_ordered_intersection([], [1,2,3])
True
>>> has_ordered_intersection([1,2,3,4], [2,5,3])
True
>>> has_ordered_intersection([1,2,3,4], [0,3,2])
False
>>> has_ordered_intersection([1,2,3,4], [1,2,5,6,7,8,5,76,4,3])
False
I used the intersection set instead of a generator because I think the extra memory is a good tradeoff compared to the time cost of shortcut-scanning the entire list per element (what in does to a list), especially if they are long.
I also don't think this should be called a "sublist" since xs is allowed to have elements that ys does not. The above relation is symmetric: swapping the arguments doesn't change the answer. A real ordered "sublist" would not be symmetric and look more like this
def is_ordered_sublist(xs, ys):
xset = {*xs}
return all(x == y for x, y in zip(xs, (y for y in ys if y in xset)))
Its easy with iterators.
>>> a = [0,1,2]
>>> b = [item for item in range(10)]
>>> b
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a
[0, 1, 2]
>>> [False, True][set([item in b for item in a]) == set([True])]
True
>>> a = [11, 12, 13]
>>> [False, True][set([item in b for item in a]) == set([True])]
False
Try this one!! sublist y is not missing the sequence of list x.
x= list
y= sublist
if ([i for i,j in enumerate(y) for k,l in enumerate(x) if i == k and j!=l]):
print("True")
else:
print("False")
I have come up with a short way to check for sublist
lst1=[1,2,5,6,8,3,2,34,3,4]
lst2=[1,2,3,4]
def sublist(lst1,lst2):
for item in lst2:
try:
lst1.index(item)
except ValueError:
return False
return True
print(sublist(lst1,lst2))
what I have done is basically take 2 lists lst1 is the larger list and lst2 is the sublist that we are checking for.
then I am taking each element of the lst2 and checking if it is in the lst1 by looking for its index
if it can't find even a single item it ..returns False
if all the items are covered it returns True
Another way is to move through all possible sublists and return once a match was found
def is_sublist(ys, xs):
for i in range(len(xs) - len(ys)):
if xs[i:i + len(ys)] == ys:
return True
return False
Find in l1 all indexes where the element match with the first element in l2, then I loop over this indexes list and for each element get the slice of l1 with the same length of l2. If the l1 slice is equal to l2, then l2 is a sublist of l1
Ex:
l1 = [1,2,3,2,1,1,3,3,4,5]
l2 = [2,1,1,3,3]
True
l1 = [1,2,3,2,1,3,3,4,5]
l2 = [2,1,1,3,3]
False
def is_sublist(l1, l2):
index_list = [i for i, v in enumerate(l1) if v==l2[0]]
for ii in index_list:
l1_slice = l1[ii:ii+len(l2)]
if l1_slice == l2:
return True
else:
return False
This code attempts to find list1 in list2 by by scanning list2. It searches list2 for the first item in list1 and then checks to see if successive items in list1 also match at the location in list2 where the first item is found. If the the first 2/4 items in list1 match at a location in list2 but the 3rd does not then it will not spend time comparing the 4th.
def ordered_sublist(l1, l2):
length = len(l1)
for i in range(len(l2) - length + 1):
if all(l1[j] == l2[j + i] for j in range(length)):
return True
return False
def lis1(item,item1):
sub_set = False
for x in range(len(item)):
if item[x] == item1[0]:
n = 1
while (n < len(item1) and (item[x + n] == item1[1])):
n += 1
if n == len(item1):
return True
return False
a = [2,3,4,5,6]
b = [5,6]
c = [2,7,6]
print(lis1(a,b))
print(lis1(a,c))
Lists are data structures where the order of the elements matters.
I understand that this question explicitly specifies "same order of indexes" but in general, when you say "sublist", this is not necessarily the only restriction that applies. The relative position between each element may also be a restriction.
In my particular case list1=[1,2,3,4] list2=[1,2,4] and list2 is not a sublist of list1, but list3=[2,3,4] is a sublist of list1.
Just for the sake of completion, I am posting here my code to find sublists where the relative index of each element also should be preserved.
def is_sublist(list1, list2):
first_index = -1
for i in range(len(list1)):
if first_index>=0:
j = i-first_index
if list1[i] != list2[j]:
return False
if j == len(list2)-1:
return True
elif list1[i] == list2[0]:
first_index = i
return False
print(is_sublist(['r1','r2','r3','r4','r6'],['r1','r2','r3']))
#>> True
print(is_sublist(['r1','r2','r3','r4','r6'],['r2','r3','r4']))
#>> True
print(is_sublist(['r1','r2','r3','r4','r6'],['r1','r2','r4']))
#>> False
#list1 = ['1','2',"4"]############works
#list2 = ['1','2',3]
lst2 = [4,8,9,33,44,67,123]
lst1 = [8,33,7] # works!
def sublist(lst1, lst2):
'checks whether list lst1 is a sublist of list lst2'
index1 = 0 # lst1 index
index2 = 0 # lst2 index
# go through indexes of lst1
while index1 < len(lst1):
# search for item in lst2 matching item in lst1 at index index1
while index2 < len(lst2) and lst1[index1] != lst2[index2]:
index2 += 1
# if we run out of items in lst2, lst1 is not a sublist of lst2
if index2 == len(lst2):
return False
index1 += 1
# every item in lst1 has been matched to an item in lst2, from left to right
return True
print( sublist(lst1, lst2))
I needed to know if the first list is the sub-list of the second one. This order was important to me. I've tried some of the solutions, but they are too 'generic' for my needs. I also wanted to make sure, that both lists are not equal. Here's the solution.
def sublist(lst1, lst2):
len1 = len(lst1)
len2 = len(lst2)
if len1 >= len2:
return False
for i in range(0, len1):
if lst1[i] != lst2[i]:
return False
return True
How about just using an index that runs along list2 as we do the comparison?
def is_ordered_sublist(lst1: list, lst2: list) -> bool:
""" Checks if lst1 is an ordered sublist of lst2 """
try:
index = 0
for item in lst1:
location = lst2[index:].index(item)
index += location + 1
return True
except ValueError:
return False
Basically for each item in list1 it simply finds the first index which it appears in the second list. Thereafter it only needs to consider the remaining parts of list2. So the worse case complexity is simple O(len(list2)).
I think this is the best way to solve this problem. This will check if list1 is a sublist of list2. We will assume that all elements are unique. If we have duplicate elements the following code will only ensure that each element of list1 is contained in list2. Hence, we do not take multiplicity into account.
list1 = [2, 3, 3, 4, 5, 9]
list2 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
set(list1).issubset(set(list2))
Definition:
List A is a sublist of list B if the exact sequence of elements of A exists in B.
An empty list is a sublist of any list.
The following function returns the index of the first occurrence of list_a in list_b, otherwise -1 is returned. For empty list_a, 0 is returned.
def sublist(list_a, list_b):
if 0 == len(list_a):
return 0
if len(list_b) < len(list_a):
return -1
idx = -1
while list_a[0] in list_b[idx+1:]:
idx = list_b.index(list_a[0], idx + 1)
if list_a == list_b[idx:idx+len(list_a)]:
return idx
return -1
Some tests:
>>> sublist([], [])
0
>>> sublist([], [1, 2, 3])
0
>>> sublist([3, 6], [1, 2, 3, 6, 3, 7, 9, 8, 0, 3, 6])
2
>>> sublist([3, 7, 9, 8], [1, 2, 3, 6, 3, 7, 9, 8, 0, 3, 6])
4
>>> sublist([3, 6, 3, 7, 9, 8, 0, 3, 6], [1, 2, 3, 6, 3, 7, 9, 8, 0, 3, 6])
2
>>> sublist([1, 2, 3, 6, 3, 7, 9, 8, 0, 3, 6, 4], [1, 2, 3, 6, 3, 7, 9, 8, 0, 3, 6])
-1
>>> sublist([3, 7, 4], [1, 2, 3, 6, 3, 7, 9, 8, 0, 3, 6])
-1
Here's a lazy-iteration, generic version for checking whether an iterable is a subsequence of another iterable:
from typing import Iterable
def is_subsequence(a: Iterable, b: Iterable) -> bool:
b_iterator = iter(b)
for x in a:
for y in b_iterator:
if y == x:
break
else:
return False
else:
return True

Python: Duplicates in list

Im trying to create a new list of unique values and remove said values from the original list so that what's left is duplicates. It appears my for loop is skipping over values.
array = [1,3,4,2,2,3,4]
def duplicates(array):
mylist = []
for item in array:
if item not in mylist:
mylist.append(item)
array.remove(item)
return mylist
results:
duplicates(array)
[1, 4, 2]
I think that using collections.Counter is more appropriate for this task:
array = [1, 3, 4, 2, 2, 3, 4]
from collections import Counter
def duplicates(array):
return [n for n, c in Counter(array).items() if c > 1]
print(duplicates(array))
Output:
[3, 4, 2]
The issue is with the array.remove(item), it is deleting the element at the index position visited. So, index number reduces by one and making the loop to skip reading the next value.
[1, 3, 4, 2, 2, 3, 4] -> before 1st iteration index 0 -> value =1
[3, 4, 2, 2, 3, 4] -> After 1st iteration 1 is removed, so index 0 -> value =3(loop not reading it as it already read index 0, so loop is reading index 1 -> value 4)
Correct code to display values without duplicates:
array = [1,3,4,2,2,3,4]
def duplicates(array):
mylist = []
for item in array:
if item not in mylist:
mylist.append(item)
#array.remove(item)
return mylist
res=duplicates(array)
print (res)
You are removing values from the list you are iterating through, so your loop is skipping values, try this
array = [1,3,4,2,2,3,4]
def duplicates(array):
mylist = []
for i, item in enumerate(array):
if item not in mylist:
mylist.append(item)
array[i] = None
array[:] = list(filter(
lambda x: x is not None,
array
))
return mylist
Though you should clarify what you want to do with array variable as it is currently unclear.
array = [1,3,4,2,2,3,4]
def duplicates(array):
mylist = []
for item in array:
if item not in mylist:
mylist.append(item)
array.remove(item)
else:
array.remove(item)
return mylist
just remove the item that you don't append
You do not need to use a loop, it is much clearer to use a list comprehension
dups = list(set([l for l in array if array.count(l) > 1]))
However, the answer provided by kuco 23 does this appropriately with a loop.
A bit unclear what result you expect. If you want to get all unique values while maintaining order of occurrence, the canonical way to achieve this would be to use a collections.OrderedDict:
from collections import OrderedDict
def duplicates(array):
return list(OrderedDict.fromkeys(array))
>>> duplicates(array)
[1, 3, 4, 2]
If you want get a list of only duplicates, i.e. values that occur more than once, you could use a collections.Counter:
from collections import Counter
def duplicates(array):
return [k for k, v in Counter(array).items() if v > 1]
>>> duplicates(array)
[3, 4, 2]

getting second smallest value from list

x = [[1,2,3,4],[4,5,0,1],[22,21,31,10]]
def minFor(x):
removingvalue = []
for i in x:
minvalue = i[0]
for j in i:
if j < minvalue:
minvalue=j
for i in range(0,len(x)):
if x==minvalue:
removingvalue = removingvalue + minvalue
return minvalue
print(minvalue)
what I 'm trying to do here is first find the smallest number from the list. And remove that smallest value and find again the smallest number from the list. But the remove function doesn't work
This finds second smallest of each sublists in the list:
lst = [[1,2,3,4],[4,5,0,1],[22,21,31,10]]
print([sorted(x)[1] for x in lst])
# [2, 1, 21]
You just needed to sort sublist in ascending order and select second value out. There is no need of removing value from list.
Personally, I'd use the builtin sorted function:
def second_min(x):
result = []
for sublist in x:
result.extend(sublist)
# this flattens the sublists
# into a single list
result = sorted(result)
return result[1]
# return the second element
And without the built-ins, replace the sorted() call with:
...
for i in range(len(result) - 1):
if result[i] > result[i + 1]:
result[i:i + 2] = [result[i + 1], result[i]]
...
Use min(iterable) and a list comprehension to get the overall minimal value.
Then use min on the same list comp with a twist: only allow values in the second list comp that are bigger then your minimal min-value:
xxxx = [[1,2,3,4],[4,5,0,1],[22,21,31,10]]
minmin = min((x for y in xxxx for x in y)) # flattening list comp
secmin = min((x for y in xxxx for x in y if x >minmin))
print(minmin,secmin)
Output:
0 1
You can convert the given data-structure, to a single list and then sort the list. The first two elements give you the answer you want. Here's what you can do:
input_list = x
new_l = []
for sl in input_list:
new_l.extend(sl)
new_l.sort()
# First two elements of new_l are the ones that you want.
remove_smallest = [sorted(i)[1:] for i in x]
get_smallest = [min(i) for i in remove_smallest]
print(remove_smallest)
print(get_smallest)
[[2, 3, 4], [1, 4, 5], [21, 22, 31]]
[2, 1, 21]
Expanded loops:
remove_smallest = []
for i in x:
remove_smallest.append(sorted(i)[1:])
get_smallest = []
for i in remove_smallest:
get_smallest.append(min(i))

Group repeated elements of a list

I am trying to create a function that receives a list and return another list with the repeated elements.
For example for the input A = [2,2,1,1,3,2] (the list is not sorted) and the function would return result = [[1,1], [2,2,2]]. The result doesn't need to be sorted.
I already did it in Wolfram Mathematica but now I have to translate it to python3, Mathematica has some functions like Select, Map and Split that makes it very simple without using long loops with a lot of instructions.
result = [[x] * A.count(x) for x in set(A) if A.count(x) > 1]
Simple approach:
def grpBySameConsecutiveItem(l):
rv= []
last = None
for elem in l:
if last == None:
last = [elem]
continue
if elem == last[0]:
last.append(elem)
continue
if len(last) > 1:
rv.append(last)
last = [elem]
return rv
print grpBySameConsecutiveItem([1,2,1,1,1,2,2,3,4,4,4,4,5,4])
Output:
[[1, 1, 1], [2, 2], [4, 4, 4, 4]]
You can sort your output afterwards if you want to have it sorted or sort your inputlist , then you wouldnt get consecutive identical numbers any longer though.
See this https://stackoverflow.com/a/4174955/7505395 for how to sort lists of lists depending on an index (just use 0) as all your inner lists are identical.
You could also use itertools - it hast things like TakeWhile - that looks much smarter if used
This will ignore consecutive ones, and just collect them all:
def grpByValue(lis):
d = {}
for key in lis:
if key in d:
d[key] += 1
else:
d[key] = 1
print(d)
rv = []
for k in d:
if (d[k]<2):
continue
rv.append([])
for n in range(0,d[k]):
rv[-1].append(k)
return rv
data = [1,2,1,1,1,2,2,3,4,4,4,4,5,4]
print grpByValue(data)
Output:
[[1, 1, 1, 1], [2, 2, 2], [4, 4, 4, 4, 4]]
You could do this with a list comprehension:
A = [1,1,1,2,2,3,3,3]
B = []
[B.append([n]*A.count(n)) for n in A if B.count([n]*A.count(n)) == 0]
outputs [[1,1,1],[2,2],[3,3,3]]
Or more pythonically:
A = [1,2,2,3,4,1,1,2,2,2,3,3,4,4,4]
B = []
for n in A:
if B.count([n]*A.count(n)) == 0:
B.append([n]*A.count(n))
outputs [[1,1,1],[2,2,2,2,2],[3,3,3],[4,4,4,4]]
Works with sorted or unsorted list, if you need to sort the list before hand you can do for n in sorted(A)
This is a job for Counter(). Iterating over each element, x, and checking A.count(x) has a O(N^2) complexity. Counter() will count how many times each element exists in your iterable in one pass and then you can generate your result by iterating over that dictionary.
>>> from collections import Counter
>>> A = [2,2,1,1,3,2]
>>> counts = Counter(A)
>>> result = [[key] * value for key, value in counts.items() if value > 1]
>>> result
[[2, 2, 2], [[1, 1]]

How to get the index of specific item in python matrix

I am newbie to Python programming language. And I am looking for How to get the indexes (line and column ) of specific element in matrix.
In other I way I want to do the same as this source code using lists.
myList=[1,10,54,85]
myList.index(54)
Best Regards
Here's a simple function which returns the coordinates as a tuple (or None if no index is found). Note that this is for 2D matrices, and returns the first instance of the element in the matrix.
(Edit: see hiro protagonist's answer for an alternative Pythonic version)
def find(element, matrix):
for i in range(len(matrix)):
for j in range(len(matrix[i])):
if matrix[i][j] == element:
return (i, j)
Or, if you want to find all indexes rather than just the first:
def findall(element, matrix):
result = []
for i in range(len(matrix)):
for j in range(len(matrix[i])):
if matrix[i][j] == element:
result.append((i, j))
return result
You can use it like so:
A = [[5, 10],
[15, 20],
[25, 5]]
find(25, A) # Will return (2, 0)
find(50, A) # Will return None
findall(5, A) # Will return [(0, 0), (2, 1)]
findall(4, A) # Will return []
a (in my opinion) more pythonic version of FlipTack's algorithm:
def find(element, matrix):
for i, matrix_i in enumerate(matrix):
for j, value in enumerate(matrix_i):
if value == element:
return (i, j)
in python it is often more natural to iterate over elements of lists instead of just the indices; if indices are needed as well, enumerate helps. this is also more efficient.
note: just as list.index (without a second argument) this will only find the first occurrence.
Since you say that you're a beginner, pardon me if you already know some of the below. Just in case I'll describe the basic logic you can use to write your own function or understand the other answers posted here better:
To access an element in a specific row of a list, for example, if you wanted to get the first element and save it in a variable:
myList=[1,10,54,85]
myvar = myList[0] # note that you access the first element with index 0
myvar now stores 1. Why index 0? Think of the index as an indicator of "how far away from the beginning of the list an element is." In other words, the first element is a distance of 0 from the start.
What if you have a multi-dimensional list like so?
multi = [[0, 1, 2],
[3, 4, 5],
[6, 7, 8]
]
Now you think in terms of row and column (and of course you could have n-dimensional lists and keep going).
How to retrieve the 5? That is a distance of 1 row from the start of the list of rows and 2 columns away from the start of the sub-list.
Then:
myvar = multi[1][2]
retrieves the 5.
FlipTack's and hiro protagonist's functions wrap this logic in the nice compact procedures, which search the entire 2-dimensional list, comparing elements until the desired one is found, then returning a tuple of the indices or continuing to search for duplicate elements. Note that if your lists are guaranteed to sorted you can then use a binary search algorithm across rows and columns and get the answer faster, but no need to worry about that for now.
Hopefully this helps.
You can also add a tag to your function to search the occurrences of your input matrix/list.
For example:
If you input is 1D vector:
def get_index_1d(a = [], val = 0, occurrence_pos = False):
if not occurrence_pos:
for k in range(len(a)):
if a[k] == val:
return k
else:
return [k for k in range(len(a)) if a[k] == val]
Output:
a = [1,10,54,85, 10]
index = get_index_1d(a, 10, False)
print("Without occurrence: ", index)
index = get_index_1d(a, 10, True)
print("With occurrence: ", index)
>>> Without occurrence: 1
>>> With occurrence: [1, 4]
For 2D vector:
def get_index_2d(a = [], val = 0, occurrence_pos = False):
if not occurrence_pos:
for k in range(len(a)):
for j in range(len(a[k])):
if a[k][j] == val:
return (k, j)
else:
return [(k, j) for k in range(len(a)) for j in range(len(a[k])) if a[k][j] == val]
Output:
b = [[1,2],[3,4],[5,6], [3,7]]
index = get_index_2d(b, 3, False)
print("Without occurrence: ", index)
index = get_index_2d(b, 3, True)
print("With occurrence: ", index)
>>> Without occurrence: (1, 0)
>>> With occurrence: [(1, 0), (3, 0)]
Just wanted to throw another solution since I didn't see it above:
def find(matrix, value):
value_indexs = [ ( matrix.index(row), row.index(value) ) for row in matrix if value in row]
return value_indexs
Example:
matrix = [
[0, 1, 2],
[3, 4, 5, 6],
[7, 8, 9, 0]
]
find(matrix, 0)
Returns: [(0,0), (2,3)]

Categories