This question already has answers here:
Access multiple elements of list knowing their index [duplicate]
(11 answers)
Closed 5 years ago.
It's fairly simple to articulate problem, but I'm not 100% sure that I have my lingo right. Nonetheless, conceptually "cherry picking" is suitable to describe the slice I have in mind. This is because I simply want to access (cherry pick from all elements) two distant elements of a list. I tried this:
my_list[2,7]
So I was expecting it to return only 2 elements, but instead I got the error:
list indices must be integers, not tuples.
I searched this error, but I found it was actually a very general error and none of the problems that instigated this error were actually for my type of problem.
I suppose I could extract the elements 1 at a time and then merge them, but my gut tells me there is a more "pythonic" way about this.
Also a slightly more complicated form of this problem I ran into was building a new list from an existing list of lists:
new_list = []
for i in range(len(my_list)):
new_list.append(my_list[i][2,7])
Normally I would just use operator.itemgetter for this:
>>> my_list = list(range(10))
>>> import operator
>>> list(operator.itemgetter(2, 7)(my_list))
[2, 7]
It also allows getting an arbitrary amount of list elements by their indices.
However you can always use NumPy (that's an external package) and it's integer slicing for this (but it won't work for normal Python lists, just for NumPy arrays):
>>> import numpy as np
>>> my_arr = np.array(my_list)
>>> my_arr[[2, 7]]
array([2, 7])
In [1]: myList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [2]: myList[2:8:5]
Out[2]: [2, 7]
myList[start:end:stride]
Hope this helps.
Related
I've had multiple scenarios, where i had to find a huge array's items in another huge array.
I usually solved it like this:
for i in range(0,len(arr1)):
for k in range(0,len(arr1)):
print(arr1[i],arr2[k])
Which works fine, but its kinda slow.
Can someone help me, how to make the iteration faster?
arr1 = [1,2,3,4,5]
arr2 = [4,5,6,7]
same_items = set(arr1).intersection(arr2)
print(same_items)
Out[5]: {4,5}
Sets hashes items so instead of O(n) look up time for any element it has O(1). Items inside need to be hashable for this to work. And if they are not, I highly suggest you find a way to make them hashable.
If you need to handle huge arrays, you may want to use Python's numpy library, which assists you with high-efficiency manipulation methods and avoids you to use loops at all in most cases.
if your array has duplicates and you want to keep them all:
arr1 = [1,2,3,4,5,7,5,4]
arr2 = [4,5,6,7]
res = [i for i in arr1 if i in arr2]
>>> res
'''
[4, 5, 7, 5, 4]
or using numpy:
import numpy as np
res = np.array(arr1)[np.isin(arr1, arr2)].tolist()
>>> res
'''
[4, 5, 7, 5, 4]
This question already has answers here:
How do I remove duplicates from a list, while preserving order?
(30 answers)
Closed 2 years ago.
I would like to get the unique element from an array with specific sequences.
For example,
initially, I have array as following:
array([3, 3, 6, 6, 5, 5, 5, 5, 2, 8, 8])
I would like to get the unique element from the array above and maintain its original order sequence. The sample output as following:
array([3, 6, 5, 2, 8])
I know that using numpy.unique() will get the unique elements for the array, but it will return sorted unique elements. However, in my case, I need the output in the original sequence.
To generate toy example, here easy for you to just copy & paste
arr = np.array([3,3,6,6,5,5,5,5,2,8,8])
At the time I post this, I still working on this, and I wish to get your suggestion so that I could move to the next part of work. Your advice will be highly appreciated. Thank you for your time!
Try this snippet:
arr = np.array([3,3,6,6,5,5,5,5,2,8,8])
unique = []
[unique.append(n) for n in arr if n not in unique]
print(np.array(unique))
This question already has answers here:
How do I concatenate two lists in Python?
(31 answers)
Closed 4 years ago.
I have a maybe stupid problem, but can't figure out how to solve it.
So basically what I'm trying to do is to:
Create a list
Add items to the list (stored in a second list)
Transform the list into a tuple
So I thought I would do something like this:
anotherList = [2,5,8]
myTuple = tuple([1,2,3].extend(anotherList))
This does not work as it throws the error:
TypeError: 'NoneType' object is not iterable
This makes sense, as the result of the extend operation is not a list. The problem is that I wasn't able to make it in a one line code, but only in a 4 lines code, like that:
anotherList = [2, 5, 8]
myList = [1, 2, 3]
myList.extend(anotherList)
myTuple = tuple(myList)
Is there a way to simplify this code? It looks unnecessarily long!
You don't want to use list.extend(), period. You are concatenating a list display (literal syntax) with another list instead, use +:
myTuple = tuple([1, 2, 3] + anotherList)
or you could convert just anotherList and prefix a tuple:
myTuple = (1, 2, 3) + tuple(anotherList)
Here the Python compiler can optimise and store the (1, 2, 3) as a constant with your code object. That initial tuple is created just once and reused across all executions.
list.extend() is intended to update an existing list object in-place via a reference to that list, but using it on a list literal means the resulting extended list has no remaining references and is discarded again.
In Python 3.5 and up you could also use the new iterable unpacking syntax:
myTuple = (1, 2, 3, *anotherlist)
Note that no tuple() call is needed there, and any iterable type (not just a list) is supported. Python 2.7 is on it's last days, you do need to start planning to move away from it.
You can add lists:
result = tuple([1,2,3] + [4,5,6])
So that'll be something like this:
anotherList = [2, 5, 8]
myList = [1, 2, 3]
myTuple = tuple(myList + anotherList)
Well, it's unclear tho, but...
Try this:
l=[2,5,8]
print(tuple([1,2,3]+l))
You can concatenate by +
Alternatively can do * (unpacking) in python 3:
print((*l, 1,2,3))
Or can do chain from itertools:
import itertools
print(tuple(itertools.chain(l, [1,2,3])))
Or merge from heapq:
from heapq import merge
print(tuple(merge(l,[1,2,3])))
Or add form operator:
import operator
print(tuple(operator.add(l, [1,2,3])))
This question already has answers here:
Understanding slicing
(38 answers)
Closed 6 years ago.
I'm a beginner attempting to learn Python. I am familiarising myself with the list data type; I've defined the following list:
>>> numbers = [1, 2, 3, 4]
Typing:
>>> numbers[0]
1
>>> numbers[1]
2
>>> numbers[2]
3
>>> numbers[3]
4
Given this, why do I get the following when I attempt to retrieve the following list elements:
>>> numbers[0:3]
[1, 2, 3]
Why isn't the list element '4' included in the response from the interpreter?
Thank you for your help.
Slice notation does not include the last element (similar to the range() function in that respect). If you want to include the last element, simply omit an index. Also, the default start is the beginning, so you don't need 0 there either:
>>> numbers[:]
[1, 2, 3, 4]
Note that this is a (shallow) copy of numbers. If you save a reference to it, you can mutate it without affecting the original numbers.
That's how slicing works in Python. To quote a tutorial:
Note how the start is always included, and the end always excluded.
This makes sure that s[:i] + s[i:] is always equal to s.
The example uses a string, but slicing works the same way with lists.
numbers[0:3] list from 0 up to 3 but 3 is excluded (like range(0,3))
For example, if I call
L = [3,4,2,1,5]
L = sorted(L)
I get a sorted list. Now, in the future, if I want to perform some other kind of sort on L, does Python automatically know "this list has been sorted before and not modified since, so we can perform some internal optimizations on how we perform this other kind of sort" such as a reverse-sort, etc?
Nope, it doesn't. The sorting algorithm is designed to exploit (partially) sorted inputs, but the list itself doesn't "remember" being sorted in any way.
(This is actually a CPython implementation detail, and future versions/different implementations could cache the fact that a list was just sorted. However, I'm not convinced that could be done without slowing down all operations that modify the list, such as append.)
As the commenters pointed out, normal Python lists are inherently ordered and efficiently sortable (thanks, Timsort!), but do not remember or maintain sorting status.
If you want lists that invariably retain their sorted status, you can install the SortedContainers package from PyPI.
>>> from sortedcontainers import SortedList
>>> L = SortedList([3,4,2,1,5])
>>> L
SortedList([1, 2, 3, 4, 5])
>>> L.add(3.3)
>>> L
SortedList([1, 2, 3, 3.3, 4, 5])
Note the normal append method becomes add, because the item isn't added on the end. It's added wherever appropriate given the sort order. There is also a SortedListWithKey type that allows you to set your sort key/order explicitly.
Some of this, at least the specific reverse sort question, could be done using numpy:
import numpy as np
L = np.array([3,4,2,1,5])
a = np.argsort(L)
b = L[a]
r = L[a[::-1]]
print L
[3 4 2 1 5]
print b
[1 2 3 4 5]
print r
[5, 4, 3, 2, 1]
That is, here we just do the sort once (to create a, the sorting indices), and then we can manipulate a, to do other various sorts, like the normal sort b, and the reverse sort r. And many others would be similarly easy, like every other element.