Extract indices of certain values from a list in python - python

Suppose, I have a list [0.5,1,1.5,2,2.5,3,3.5,4,4.5], now I would like to extract the indices of a list [1.5,2.5,3.5,4.5], which is a subset of that list.

You can use the inbuilt function <list>.index to find the index of each element(of second list) in the first list.
Having that learnt, you can use list comprehension to achieve what you want:
>>> list1 = [0.5,1,1.5,2,2.5,3,3.5,4,4.5]
>>> list2 = [1.5,2.5,3.5,4.5]
>>> [list1.index(elem) for elem in list2]
[2, 4, 6, 8]

One other option is to use enumerate function. See the following answer:
a = [0.5,1,1.5,2,2.5,3,3.5,4,4.5]
b = [1.5,2.5,3.5,4.5]
indexes = []
for id, i in enumerate(a):
if i in b:
indexes.append(id)
print(indexes)
The output is going to be [2, 4, 6, 8].

Related

Ideas for the following function?

I would like to develop a function which would always based on the first element in the list extract further elements of the nested list.
Example:
Input:
lst= [[1,2,3],[3,4,5,6,8,9], [0,3,4], [1,4,5,6], [4,9,8,6,5,2]]
The first element in the sublist always determines the number of following elements to append to a new list.
Output:
Out=[2,4,5,6,4,9,8,6,5]
Elements are always an integer values.
Maybe this is what you expect:
Or you can convert this to List Comprehension later.
out = []
for sub in lst: # loop each sublist
start = sub[0] # use the first num. to determine
out.extend(sub[1: 1+start]) # get each sublist by slicing
print(out)
[2, 4, 5, 6, 4, 9, 8, 6, 5]

Removing duplicate from list using list comprehension lead to all Nones

I tried the following code to remove duplicates from list using list comprehension
lists = [1, 2, 2, 3, 4, 3, 5, 6, 1]
unique_lists = []
[unique_lists.append(x) for x in lists if x not in unique_lists]
print(unique_lists)
unique_lists = []
g = [unique_lists.append(x) for x in lists if x not in unique_lists]
print(g)
The printed result are shown as below
[1, 2, 3, 4, 5, 6]
[None, None, None, None, None, None]
I'm trying to understand why the 2nd method (simply by assigning the list to g, returns all None? Thanks.
It's because list.append() always returns None. The easy way to do what you want is to convert it to a set.
unique_lists = list(set(lists))
list.append returns None. What you could do is use a set to remember the unique numbers:
lists = [1, 2, 2, 3, 4, 3, 5, 6, 1]
uniques = set()
unique_lists = [x for x in lists if not (x in uniques or uniques.add(x))]
Or a more efficient way would be to use how dict's act similar to a set while keeping insertion order (in python3+):
unique_lists = list(dict.fromkeys(lists))
You can also check this question for more answers/explanation on how to remove dups from a list.
Using a set to select the 1st occurrence of each distinct element will be more efficient than a list. You can even embed this control set in the comprehension:
g = [x for s in [set()] for x in lists if x not in s and not s.add(x)]
if you're not concerned with performance, you could select the item based on the index of their first occurrence:
g = [x for i,x in enumerate(lists) if i==lists.index(x)]
There is also a trick you can do using a dictionary:
g = list(dict(zip(lists,lists)))

Unique list of lists

I have a nested list as an example:
lst_a = [[1,2,3,5], [1,2,3,7], [1,2,3,9], [1,2,6,8]]
I'm trying to check if the first 3 indices of a nested list element are the same as other.
I.e.
if [1,2,3] exists in other lists, remove all the other nested list elements that contain that. So that the nested list is unique.
I'm not sure the most pythonic way of doing this would be.
for i in range(0, len(lst_a)):
if lst[i][:3] == lst[i-1][:3]:
lst[i].pop()
Desired output:
lst_a = [[1,2,3,9], [1,2,6,8]]
If, as you said in comments, sublists that have the same first three elements are always next to each other (but the list is not necessarily sorted) you can use itertools.groupby to group those elements and then get the next from each of the groups.
>>> from itertools import groupby
>>> lst_a = [[1,2,3,5], [1,2,3,7], [1,2,3,9], [1,2,6,8]]
>>> [next(g) for k, g in groupby(lst_a, key=lambda x: x[:3])]
[[1, 2, 3, 5], [1, 2, 6, 8]]
Or use a list comprehension with enumerate and compare the current element with the last one:
>>> [x for i, x in enumerate(lst_a) if i == 0 or lst_a[i-1][:3] != x[:3]]
[[1, 2, 3, 5], [1, 2, 6, 8]]
This does not require any imports, but IMHO when using groupby it is much clearer what the code is supposed to do. Note, however, that unlike your method, both of those will create a new filtered list, instead of updating/deleting from the original list.
I think you are missing a loop For if you want to check all possibilities. I guess it should like :
for i in range(0, len(lst_a)):
for j in range(i, len(lst_a)):
if lst[i][:3] == lst[j][:3]:
lst[i].pop()
Deleting while going throught the list is maybe not the best idea you should delete unwanted elements at the end
Going with your approach, Find the below code:
lst=[lst_a[0]]
for li in lst_a[1:]:
if li[:3]!=lst[0][:3]:
lst.append(li)
print(lst)
Hope this helps!
You can use a dictionary to filter a list:
dct = {tuple(i[:3]): i for i in lst}
# {(1, 2, 3): [1, 2, 3, 9], (1, 2, 6): [1, 2, 6, 8]}
list(dct.values())
# [[1, 2, 3, 9], [1, 2, 6, 8]]

outcome first list in 2 dimensional list

I have a 2 Dimensional list like that :
list = [[2, 3, 5], [1,2,3], [4,5,6], [8,9,10],[5,6,7]]
I can print the first value of every list with this:
[i[0] for i in list]
and outcome is:
list = [2, 1, 4, 8, 5]
but i want to have outcome like this :
list = [[2,3,5],[1,2,3],[4,5,6]]
my code is this :
new_list = []
for i in list:
row = 1
row_list = list[row]
new_list.append(row_list)
can anyone help me?
I am a bit confused what are you asking, but if I get i right try
print(list[1][1]) #print 2nd element in 2nd subset
print(list[0:3]) #print first 3 elements (in this case subsets) in the list
I hope it help.
To remove few object from list, you can use
list.remove(something) #remove element from list
or to create new list just use
l=list[0:3]
but i want to have outcome like this : list = [[2,3,5],[1,2,3],[4,5,6]]
This should do it:
list_subset = list[:3] # the first 3 elements in the list
you can slice your list like this:
n = 3 # if you have number of items you need
new_list = list[:n]
or:
n = 2 # if you have number of items you want to remove
new_list = list[:-n]
note that:
DO NOT use list as a name of a variable, list is a built-in in python.
Simple slicing can be used to skip last two rows like this:
list = [[2, 3, 5], [1,2,3], [4,5,6], [8,9,10],[5,6,7]]
print(list[:-2])
[[2, 3, 5], [1, 2, 3], [4, 5, 6]]

List Duplicate Removal Issue?

I wrote a code that eliminates duplicates from a list in Python. Here it is:
List = [4, 2, 3, 1, 7, 4, 5, 6, 5]
NewList = []
for i in List:
if List[i] not in NewList:
NewList.append(i)
print ("Original List:", List)
print ("Reworked List:", NewList)
However the output is:
Original List: [4, 2, 3, 1, 7, 4, 5, 6, 5]
Reworked List: [4, 2, 3, 7, 6]
Why is the 1 missing from the output?
Using set() kills the order. You can try this :
>>> from collections import OrderedDict
>>> NewList = list(OrderedDict.fromkeys(List))
You missunderstood how for loops in python work. If you write for i in List: i will have the values from the list one after another, so in your case 4, 2, 3 ...
I assume you thought it'd be counting up.
You have several different ways of removing duplicates from lists in python that you don't need to write yourself, like converting it to a set and back to a list.
list(set(List))
Also you should read Pep8 and name your variables differently, but that just btw.
Also if you really want a loop with indices, you can use enumerate in python.
for idx, value in enumerate(myList):
print(idx)
print(myList[idx])
Your code is not doing what you think it does. Your problem are these two constructs:
for i in List: # 1
if List[i] # 2
Here you are using i to represent the elements inside the list: 4, 2, 3, ...
Here you are using i to represent the indices of the List: 0, 1, 2, ...
Obviously, 1. and 2. are not compatible. In short, your check is performed for a different element than the one you put in your list.
You can fix this by treating i consistently at both steps:
for i in List:
if i not in NewList:
NewList.append(i)
Your method for iterating over lists is not correct. Your code currently iterates over elements, but then does not use that element in your logic. Your code doesn't error because the values of your list happen also to be valid list indices.
You have a few options:
#1 Iterate over elements directly
Use elements of a list as you iterate over them directly:
NewList = []
for el in L:
if el not in NewList:
NewList.append(i)
#2 Iterate over list index
This is often considered anti-pattern, but is not invalid. You can iterate over the range of the size of the list and then use list indexing:
NewList = []
for idx in range(len(L)):
if L[idx] not in NewList:
NewList.append(i)
In both cases, notice how we avoid naming variables after built-ins. Don't use list or List, you can use L instead.
#3 unique_everseen
It's more efficient to implement hashing for O(1) lookup complexity. There is a unique_everseen recipe in the itertools docs, replicated in 3rd party toolz.unique. This works by using a seen set and tracking items as you iterate.
from toolz import unique
NewList = list(unique(L))

Categories

Resources