A=[2,3,5,7,11,13]
print(A.index(5))
The answer is 2,
But what I need is the first one which is bigger than 4 (the answer will be the same - 2).
I can apply a while loop, but is there a more elegant or a builtin way to do it?
In my problem the list is sorted in an ascending order (no duplication),
and my target is to split it into two lists: lower or equal to 4, and bigger than 4; and given the list is sorted it would be redundant to scan it twice (or even once).
As #DanD.mentioned, you can use the bisect module for this, in you example you can use bisect_left
>>> import bisect
>>> bisect.bisect_left(A, 5)
2
This will use a binary search since your data is sorted, which will be faster than a linear search (O(logN) instead of O(N)).
If you want the index of the first value greater than 4, then you can switch to bisect_right
>>> bisect.bisect_right(A, 4)
2
You're totally correct about efficiency - if you have already sorted list, do not iterate linearly, its waste of time
There's built-in bisect module - exactly for binary search in sorted containers.
You're probably looking for bisect_right function.
Thanks everybody, the answer using your kind help is:
import bisect
A=[2,3,5,7,11,13]
N=bisect.bisect_right(A,4)
print(A[:N]) #[2,3]
print(A[N:]) #[5,7,11,13]
Use next with a default argument:
val = next((i for i, x in enumerate(A) if x > 4), len(A))
Given the above result, you can then do:
left, right = A[:val], A[val:]
Related
Given a list like the next one:
foo_list = [[1,8],[2,7],[3,6]]
I've found in questions like Tuple pairs, finding minimum using python and
minimum of list of lists that the pair with the minimum value of a list of lists can be found using a generator like:
min(x for x in foo_list)
which returns
[1, 8]
But I was wondering if there is a similar way to return both minimum values of the "columns" of the list:
output = [1,6]
I know this can be achieved using numpy arrays:
output = np.min(np.array(foo_list), axis=0)
But I'm interested in finding such a way of doing so with generators (if possible).
Thanks in advance!
[min(l) for l in zip(*foo_list)]
returns [1, 6]
zip(*foo_list) gets the list transpose and then we find the minimum in both lists.
Thanks #mousetail for suggestion.
You can use two min() for this. Like -
min1 = min(a for a, _ in foo_list)
min2 = min(b for _, b in foo_list)
print([min1, min2])
Will this do? But I think if you don't want to use third party library, you can just use plain old loop which will be more efficient.
I realise that there's a fair chance this has been asked somewhere else, but to be honest I'm not sure exactly what terminology I should be using to search for it.
But basically I've got a list with a varying number of elements. Each element contains 3 values: A string, another list, and an integer eg:
First element = ('A', [], 0)
so
ListofElements[0] = [('A', [], 0)]
And what I am trying to do is make a new list that consists of all of the integers(3rd thing in the elements) that are given in ListofElements.
I can do this already by stepping through each element of ListofElements and then appending the integer onto the new list shown here:
NewList=[]
for element in ListofElements:
NewList.append(element[2])
But using a for loop seems like the most basic way of doing it, is there a way that uses less code? Maybe a list comprehension or something such as that. It seems like something that should be able to be done on a single line.
That is just a step in my ultimate goal, which is to find out the index of the element in ListofElements that has the minimum integer value. So my process so far is to make a new list, and then find the integer index of that new list using:
index=NewList.index(min(NewList))
Is there a way that I can just avoid making the new list entirely and generate the index straight away from the original ListofElements? I got stuck with what I would need to fill in to here, or how I would iterate through :
min(ListofElements[?][2])
You can use a list coprehension:
[x[2] for x in ListOfElements]
This is generally considered a "Pythonic" approach.
You can also find the minimum in a rather stylish manner using:
minimum = min(ListOfElements, key=lambda x: x[2])
index = ListOfElements.index(minimum)
Some general notes:
In python using underscores is the standard rather than CamelCase.
In python you almost never have to use an explicit for loop. Instead prefer
coprehensions or a functional pattern (map, apply etc.)
You can map your list with itemgetter:
>>> from operator import itemgetter
>>> l = [(1, 2, 3), (1, 2, 3), (1, 2, 3), (1, 2, 3), (1, 2, 3)]
>>> map(itemgetter(2), l)
[3, 3, 3, 3, 3]
Then you can go with your approach to find the position of minimum value.
Suppose I have a string PRIME on a list ['P','R','I','M','E']. If we iterate through the list, the first element 'P' has 3 elements less than it which is ['I','M','E'] and the second element 'R' has only three elements less than it (note that we are looking for smaller elements going forward in the list so while looking for elements smaller than 'R', 'P' would not be considered as we are done with it) so the positional list would be [3,3,1,1,0] in above example. I could do this in o(n**2) time by using a nested loop but is there any way to do this in o(n)? I tried something like this but it failed horribly:
for _ in range(int(input())):
x=list(input())
y=sorted(x)
lis=[]
for _ in x:
res=abs(y.index(_)-x.index(_))
lis.append(res)
print(lis)
Here is mine (not O(n), but not O(n^2) either I guess):
>>> def find_dict_position(s):
from collections import defaultdict
counter = defaultdict(int)
result = []
less_count = 0
for e in s[::-1]:
less_count = sum(counter[c] for c in counter if c<e)
result.append(less_count)
counter[e] += 1
return reversed(result)
>>> list(find_dict_position('PRIME'))
[3, 3, 1, 1, 0]
Regardless of whether if you can do this in a smaller complexity or not, you can use a list comprehension and a generator expression as follows to make your code faster and more Pythonic.
In [7]: [sum(j > t for t in lst[i+1:])for i, j in enumerate(lst)]
Out[7]: [3, 3, 1, 1, 0]
Also, Note that you cannot do this in O(n), because after all you need to compare your elements together which is a sorting type algorithm that in best case can be done in O(nlong(n)).
So basically this problem is finding the count of smaller elements on the right side of current position in an array. First replace character array with their respective ASCII values. That you can use balanced BST to solve the problem.
Here is the detailed explanation for the finding count of smaller elements on the right side in an array . Complexity O(nLogn).
But here as array elements are only characters it can be done in O(n) complexity as per algorithm written in mshsayem’s answer.
So I know that to get a single column, I'd have to write
a = list(zip(*f)[0])
and the resulting a will be a list containing the first element in the lists in f.
How do I do this to get more than one element per list? I tried
a = list(zip(*f)[1:19])
But it just returned a list of lists where the inner list is the composed of the ith element in every list.
The easy way is not to use zip(). Instead, use a list comprehension:
a = [sub[1:19] for sub in f]
If it is actually the second half that you are looking for:
a = [sub[len(sub) // 2:] for sub in f]
That will include the 3 in [1, 2, 3, 4, 5]. If you don't want to include it:
a = [sub[(len(sub) + 1) // 2:] for sub in f]
You should definitely prefer #zondo's solution for both performance and readability. However, a zip based solution is possible and would look as follows (in Python 2):
zip(*zip(*f)[1:19])
You should not consider this cycle of unpacking, zipping, slicing, unpacking and re-zipping in any serious code though ;)
In Python 3, you would have to cast both zip results to list, making this even less sexy.
To find the maximal value in a matrix of numbers, we can code 5 lines to solve the problem:
ans = matrix[0][0]
for x in range(len(matrix)):
for y in range(len(matrix[0])):
ans = max(ans, matrix[x][y])
return ans
Is there a one line solution for this problem?
The one that I came up with is pretty awkward actually:
return max(max(matrix, key=max))
or
return max(map(max, matrix))
You can use generator expression to find the maximum in your matrix. That way you can avoid building the full list of matrix elements in memory.
maximum = max(max(row) for row in matrix)
instead of list comprehension as given in a previous answer here
maximum = max([max(row) for row in matrix])
This is from PEP (the rationale section):
...many of the use cases do not need to have a full list created in
memory. Instead, they only need to iterate over the elements one at a
time.
...
Generator expressions are especially useful with functions like sum(), min(), and max() that reduce an iterable input to a single value
...
The utility of generator expressions is greatly enhanced when combined with reduction functions like sum(), min(), and max().
Also, take a look at this SO post: Generator Expressions vs. List Comprehension.
By matrix, I assume you mean a 2d-list.
max([max(i) for i in matrix])
using numpy.amax:
import numpy as np
>>> my_array
array([[1, 2, 3],
[9, 8, 6]])
>>> np.amax(my_array)
9
You can also flatten your array:
from itertools import chain
flatten = chain.from_iterable
max(flatten(matrix))