For a list
a= [1,2,5,3,7,2,3,1,7,4,2,3,4,2,1]
i know that if i do this
a.index(2)
1
However I want want to know what is the cleanest way to find a number from a certain point.
a.index(2,from point 2)
5
The list.index [doc] function has extra parameters:
list.index(x[, start[, end]])
Return zero-based index in the list of the first item whose value is x. Raises a ValueError if there is no such item.
The optional arguments start and end are interpreted as in the slice notation and are used to limit the search to a particular subsequence of the list. The returned index is computed relative to the beginning of the full sequence rather than the start argument.
So you can use:
a.index(2, 2)
to start searching from index 2 (including index 2).
via implementation of list.index, you can pass your "point" to achieve your desired output:
a= [1,2,5,3,7,2,3,1,7,4,2,3,4,2,1]
print(a.index(2, 2))
Output:
5
However, another possible solution is to built a dictionary:
val = 2
a= [1,2,5,3,7,2,3,1,7,4,2,3,4,2,1]
locations = dict(enumerate([i for i, c in enumerate(a) if c == val], start=1))
print(locations.get(2, False))
Output:
5
Related
I have this exercise that I fail to understand
Suppose we are given a list X of integers. We need to construct a sequence of indices (positions) of the elements in this list equal to the maximal element. The indicies in the sequence are in the ascending order.
Hint use the enumerator function
from typing import Iterator
X = [1,10,3,4,10,5]
S : Iterator[int] = YOUR_EXPRESSION
assert list(S)==[1,4]
This is the only thing I could come up with, but for sure it does not return [1,4]
If you wondering what I don't understand, it is not clear from reading the description how it could return [1,4].
Maybe you want to try to explain that to me first...
This is my (wrong) solution
my_enumerate=enumerate (X)
my_enumerate=(list(my_enumerate))
my_enumerate.sort(reverse=True)
So you have the list X containing [1,10,3,4,10,5]. The maximal, or largest, element is 10. Which means we should return a list of all the indices where we find 10. There are two 10s at index 1 and 4 respectively.
Using enumerate you get at each iteration the index and element. You can use that to filter out the elements you don't need. List comprehensions are useful in this case, allowing for filtering with the if syntax i.e. [val for val in items if some_condition]
you can use a generator like this
max_val=max(X)
s = (i for i, v in enumerate(X) if v==max_val)
This is my solution
( x[0] for x in enumerate (X) if x[1] == max(X) )
this is the book solution
(i for (i, n) in enumerate(X) if n == max(X))
This requires two steps:
Determine the maximum value with max
Iterate the indices of your list and retain those that have this maximum value
To avoid a bad time complexity, it is necessary to not repeat the first step:
S : Iterator[int] = (lambda mx:
(i for i, x in enumerate(X) if x == mx)
)(max(X))
The reason for presenting the code in such ugly expression, is that in the question it seems a requirement to follow the template, and only alter the part that is marked with "YOUR_EXPRESSION".
This is not how you would write it without such artificial constraints. You would just do mx = max(X) and then assign the iterator to S in the next statement without the need for this inline lambda.
def test(numbers):
e = [int(i) % 2 == 0 for i in numbers.split()]
return e.index(True) + 1 if e.count(True) == 1 else e.index(False) + 1
#the question was to identify the index position of the odd number
i understood the list comprehension part, but i am not getting the boolean part here. it would be a great help if somebody helps me get through this.
Can anybody help me from return ?
e is a python list. The e.index and e.count methods are instance methods on the list. See https://docs.python.org/3/tutorial/datastructures.html#more-on-lists for more information.
list.index(x[, start[, end]])
Return zero-based index in the list of the first item whose value is equal to x. Raises a ValueError if there is no such item.
The optional arguments start and end are interpreted as in the slice notation and are used to limit the search to a particular subsequence of the list. The returned index is computed relative to the beginning of the full sequence rather than the start argument.
list.count(x)
Return the number of times x appears in the list.
So in your case, e.count(True) counts how many times True appears in the list. If there is only one True value, then the index of that value + 1 is returned. Otherwise, the index of the first False value + 1 is returned.
I'm solving a puzzle that takes in a list, loops through each index and sums the values to the left and to the right of the current index. If it finds an index at which the sum of the values to its left are equal to the sum of the values to its right, then return that index.
For example:
[1,2,3,4,3,2,1]
If I am at index 3 (value 4), we see that the sum of values of elements to its left and right are equal.
(1 + 2 + 3) = (3 + 2 + 1).
However, when the input is a list of negative values, it returns a negative index. This is my code:
def get_equal_sum(list):
for i in list:
if sum(list[:i]) == sum(list[i+1:]):
print i
list = [1,2,3,4,3,2,1]
get_equal_sum(list)
>>> 3
list = [-1,-2,-3,-4,-3,-2,-1]
get_equal_sum(list)
>>> -4
Why is it returning -4 and not 3?
Thank you!
When you do
for i in list:
if sum(list[:i]) == sum(list[i+1:]):
i is not the index of the list but the value. The fact that it doesn't crash with IndexError when you feed the slices with negative values is because negative indexing is supported in python (indexes from the end of the list) as long as absolute value is in range (which is the case here). That's probably why you missed that.
If you want indexes you have to use enumerate for instance:
for i,_ in enumerate(l):
if sum(l[:i]) == sum(l[i+1:]):
(and change list to l because list is the list type)
Note the i,_ notation to unpack index/value and discard the value which isn't needed here. You could also go with the classical:
for i in range(len(l)):
for i in list:
...
This goes through the values of list, not the index (hence you why you get -4), to go through index you must use xrange (or range for python 3) over the len(list)
for i in xrange(len(list)):
...
or use enumerate(list). enumerate returns a tuple of the index value pair on any iteratable object, so you would index over a list like this:
for index, value in enumerate(list):
...
In this situation index is likely your i. Additionally, you do not want to shadow names already used by python itself (ie list or max, or min abs etc...) this will overwrite those variables to be what you assign them to in your program. For example, list is no longer a function that can create a list from list(iterable), but is now what ever you assign it to, you can no longer use it the default python way. Here is a list of python 2.7 built function in names
Because -4 is at index -4. You can have negative indices in Python with index -1 being the last element in a list.
I am using build-in function zip() to compare 2 element in List.
myList =[11,12,93,14,15,45,56,67,78,11]
z = 0;
final = 0 ;
for x, y in zip(myList, myList[1:]):
if x > y :
z = x
if (final<x):
final = x;
print final;
For this code I get valid answer as: 93
Now if I add another element in last index as 333
myList =[11,12,93,14,15,45,56,67,78,11,333]
z = 0;
final = 0 ;
for x, y in zip(myList, myList[1:]):
if x > y :
z = x
if (final<x):
final = x;
print final;
I get still get output as :93 , but the correct answer in 333.
Can someone explain the logic as where I am wrong.
zip stops at the end of its shortest argument. myList[1:] is always one shorter than myList (provided the list isn't empty), and so the last pair you get from zip is x,y = 11,333:
>>> myList =[11,12,93,14,15,45,56,67,78,11,333]
>>> pairs = zip(myList, myList[1:])
>>> list(pairs)[-1]
(11, 333)
But you only ever assign final and z to the current value of x, which can never be the last element. You could add a phantom element to the end of the list that can't trigger the conditions: you're using mixed greater and lesser comparisons, so your best option is the special value "not a number" float('nan'), which is neither bigger nor smaller than any number (all comparisons return False). For the special case of pairs, you can put the dummy element in like this since the second argument is known to be exactly one element shorter than the longer one:
>>> pairs = zip(myList, myList[1:]+[float('nan')])
>>> list(pairs)[-1]
(333, nan)
But for a more general solution, you will want to use zip_longest from itertools, which effectively pads the end of the shorter arguments like this until they are the length of the longest one:
>>> pairs = it.zip_longest(myList, myList[1:], fillvalue=float('nan'))
>>> list(pairs)[-1]
(333, nan)
Take a look at itertools.izip_longest, as you are attempting to zip together iterables that are different in length. izip_longest will allow you to add a fill value for the iterables that are shorter than the longest one.
The reason this happens is because zip has length equal to the shortest sequence. Note that in the first case your list is of even length (so all pairs are returned), but in the second, it's odd, so you don't get the last one. If you wanted different behavior, take a look at itertools.izip_longest.
I was trying to sort list of lists in python but it doesn't seem to work.
def get(l):
return l[1]
def com(x,y):
return len(x) < len(y)
x = [['jis','1,2334'],['hshshau','123'],['sjuaj','3214']]
x.sort(cmp=com,key=get)
Output
[['jis', '1,2334'], ['hshshau', '123'], ['sjuaj', '3214']]
How to achieve list in increasing order of 2nd element ? Thanks.
You don't need cmp here just use a key :
>>> x = [['jis','1,2334'],['hshshau','123'],['sjuaj','3214']]
>>>
>>> x.sort(key=lambda x:len(x[1]))
>>> x
[['hshshau', '123'], ['sjuaj', '3214'], ['jis', '1,2334']]
>>>
And you need to know that sort function will sort the list elements based on the key and here your key doesn't consider the length of your elements. you just sorting based on second element and sort will sort your list based on second element lexicographicaly!
For more information about python sort function read https://docs.python.org/2/library/functions.html#sorted
Like #Kasra said you do not need to use the cmp parameter, you can just use the key , also if you want to consider the second element as integers (numbers) you can replace',' with '' (Assuming only , will come in that) (empty string) and then convert to int and use, so that numbers of same length are also sorted correctly.
Example -
>>> x = [['jis','1,2334'],['hshshau','123'],['sjuaj','3214'],['nbhd','1,841']]
>>> x.sort(key = lambda x: int(x[1].replace(',','')))
>>> x
[['hshshau', '123'], ['nbhd', '1,841'], ['sjuaj', '3214'], ['jis', '1,2334']]
From the documentation for cmp argument -
cmp specifies a custom comparison function of two arguments (iterable elements) which should return a negative, zero or positive number
As you can see above, cmp function needs to return 0 if both are equal, positive number if the first is greater and negative number if the first is less than the second argument.
But in your case you are returning a boolean value, causing the issue.