Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
data = [10, 90, 20, 80, 30, 40, 70, 60]
A_list=[A,B,C,D,E,F,G,H]
How do I find all the values in data that are above 50.
Next how do I print so that it displays
B:90
D:80
H:60
G:70
Also I haven't used enumerate yet.
If you just want to print all the values higher then 50 a simple loop will do.
data = [10, 90, 20, 80, 30, 40, 70, 60]
for value in data:
if value > 50:
print(value)
If you need the indexes use this code. enumerate will give you an automatic counter.
data = [10, 90, 20, 80, 30, 40, 70, 60]
for index, value in enumerate(data):
if value > 50:
print(index)
If you need a list of indexes to print the values (your question is unclear at that point) then construct this list and loop over it.
data = [10, 90, 20, 80, 30, 40, 70, 60]
indexes = [index for index, value in enumerate(data) if value > 50]
for index in indexes:
print(data[index])
According to the question in your comment you could do the following (based on the last solution).
data = [10, 90, 20, 80, 30, 40, 70, 60]
characters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
indexes = [index for index, value in enumerate(data) if value > 50]
for index in indexes:
print('{}: {}'.format(characters[index], data[index]))
This code uses the index for both lists.
If this is homework and you can't use enumerate you have to construct the indexes list with a standard for loop.
indexes = []
for index in range(len(data)):
if data[index] > 50:
indexes.append(index)
A pythonic solution would be something like this.
data = [10, 90, 20, 80, 30, 40, 70, 60]
characters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
for char, value in zip(characters, data):
if value > 50:
print('{}: {}'.format(char, value))
In case you want the elements of the list which are greater than 50, you can simply use a list comprehension:
[el for el in lst if el>50]
where lst is your input list.
If you also wanted the index of those elements, you could:
[(i,el) for (i,el) in enumerate(lst) if el>50]
which would give you a list of tuples (index, element)
You want an if loop; if x is greater than one of the numbers, print it?
example:
myList = list(range(0,100))
for numb in myList:
if numb > 50:
print numb
Honestly, I'm not sure what OP wants to do. But this is just an example.
If you would like to use enumerate(), and you would like to store both the indexes of the numbers above 50 and the values themselves, one way would be to do it like so:
>>> a = [1,2,3,4,5,50,51,3,53,57]
>>> b, c = zip(*[(d, x) for d, x in enumerate(a) if x > 50])
>>> print b
(6, 8, 9)
>>> print c
(51, 53, 57)
Enumerate takes any object that supports iteration, and returns a tuple, (count, value), when the next() method of the iterator is called. Since enumerate() defaults to start its count at 0, and increments the count by one each iteration, we can use it to count the index of the array that the iteration is currently on.
Now, our list comprehension is returning a list of tuples, if we were to print the comprehension we would get:
>>> print [(d, x) for d, x in enumerate(a) if x > 50]
[(6, 51),(8, 53),(9, 57)]
Zip creates a list of tuples when given two arrays, for example:
>>> f = [1, 2, 3]
>>> g = [4, 5, 6]
>>> zipped = zip(f, g)
>>> zipped
[(1, 4), (2, 5), (3, 6)]
When used with the * operator, zip() will "unzip" a list.
So, when we "unzip" the list comprehension, two tuples are returned.
Hope this helps!
Related
I have written a function that collects all index positions of 'NULL' and 'NaN' strings that appear in a list and append them to another list called num. I am now trying to write a function that goes through the list that holds the strings 'NULL' and 'NaN' and uses the index positions from the num list to remove them.
I have coded these so far without success.
l = ['NULL', 32, 43, 'NaN', 45, 89, 11, 'NULL']
num = [0, 3, 7]
def rowRemover():
for i in num:
l.pop(num[i])
rowRemover()
print(l)
def rowRemover():
i = 0
while i < len(num):
l.pop(num[i])
i += 1
rowRemover()
print(l)
I would appreciate your help. Thanks
Instead of popping elements from a list, consider a list comprehension. Since we'll be checking if indices match and checking if an item exists in a set is cheaper than doing the same with a list, convert num to num_set. Then enumerate function will help you identify which elements to exclude:
l = ['NULL', 32, 43, 'NaN', 45, 89, 11, 'NULL']
num_set = set([0, 3, 7])
new_l = [x for i, x in enumerate(l) if i not in num_set]
Output:
[32, 43, 45, 89, 11]
My issue is as follows: I want to create a program that accepts a random list (l) from the list. This randomly chosen list, in its turn, contains other lists. Then it should find the shortest list inside l and cut all other lists inside l by the length of the shortest one. These lists should be appended to a new list (l_exit) as follows: [l[1][1], l[2][1], ... , l[i][1], l[1][2], ... , l[i][k]]. Then all elements, which have been cut, should be added to the end of l_exit.
Input: [[1,2,3],['a', 'b'], [30, 40, 50, 60]]
Output: [1, 'a', 30, 2, 'b', 40], [3, 50, 60]
(shortest length is 2 (['a','b']). we cut every list by 2 and
therefore have new following lists [1,2],['a','b'],[30,40]. They are
added accordingly to l_exit[0] (firstly go first elements of each
list, secondly - second and so on). In the end we add a new list of
items that have been left, that have been cut from pre-existing lists: 3,50,60)
When I try running the program with above-mentioned input, I have the following output:
changed l: [[1, 2, 3], ['a', 'b'], [30, 40, 50, 60]]
l_exit: [[40, 'b', 2, 30, 'a', 1, 1],[]]
What can be the source of the problem? I will appreciate any help! Thanks in advance!
The program:
import random
l_1 = [[1,2,3],['a', 'b'], [30, 40, 50, 60]]
l_2 = [[1,2,3,4,5],['a', 'b','c'], [30, 40, 50, 120]]
l_3 = [[1],['a', 'b'], [30, 40, 50, 60, 101, 120]]
l_rand = [l_1,l_2,l_3]
l = random.choice(l_rand)
l_exit = [[],[]]
if (len(l[1]) < len(l[2])):
index = len(l[1])
else:
index = len(l[2])
for i in range (len(l)):
if (len(l[i]) < index):
l_exit[1] = l[i][index:]
l[i] = l[i][:index]
for i in range (index):
for k in range(len(l)):
l_exit.insert(0,(l[k][i]))
print('changed l:', l)
print('l_exit: ', l_exit)
You can use the zip function to get your first part. First we 'unpack' using the *, then we loop over the lists:
x = [[1,2,3],['a', 'b'], [30, 40, 50, 60]]
out = []
for i in zip(*x):
out.extend([*i])
out
#[1, 'a', 30, 2, 'b', 40]
zip finishes at the shortest element, so we are done.
To get the remainder list, we can do a little extra work to figure out where we finished, using a counter, and then subset the original lists:
out = []
left = []
count = 0
for i in zip(*x):
out.extend([*i])
count += 1
for i in x:
left.extend(i[count:])
out, left
#([1, 'a', 30, 2, 'b', 40], [3, 50, 60])
Defining index
Firstly, there is an issue in the following if/else tree:
if (len(l[1]) < len(l[2])):
index = len(l[1])
else:
index = len(l[2])
What happens in the case that l[0] is the shortest list within l? Or cases in which the longest list within l has an index >2?
If index is to be defined as "An integer representing the len of the shortest list stored within l" then I would suggest the following:
index = len(sorted(l, key=len)[0])
The code is quite concise and basically runs as "The value of index is the len of the first list stored in a copy of l that has been sorted by len". This will stop unexpected/undesirable behaviour that may be generated by your original index definition as discussed above.
Populating l_exit
As far as I understand, l_exit should be a list containing:
A list containing all values up to (but not including as to account for index from 0) the index of index from each list within l - stored in l_exit[0]
A list containing all values from the index of index from each list within l - stored in l_exit[1]
First you try to populate l_exit[1] using the following loop:
for i in range (len(l)):
if (len(l[i]) < index):
l_exit[1] = l[i][index:]
l[i] = l[i][:index]
The problem here is that given index refers to a value that is the shortest len of an element in the top-level of the list l (as discussed previously this may not be reliable in the current implementation but would be in the example output you provided), the code held in the if len(l[i]) < index): block will never execute - since by definition no len(l[i]) for i in l could be < index.
Conclusion
I won't go into further detail on issues within your code here as I feel it is obvious that you should spend some time reviewing each statement/structure, debugging with a debugger or console printouts as best fits your attitude - could you state what each line of your code is doing if asked?
I would however recommend looking into the built-in enumerate() method - enumerate docs - as I feel that you might be able to use this to good effect as to improve the readability/maintainability of your code.
Solution
I think it would be time well spent to review your existing code yourself, but for what it's worth here's my full solution to the problem posed.
import random
l_1 = [[1,2,3],['a', 'b'], [30, 40, 50, 60]]
l_2 = [[1,2,3,4,5],['a', 'b','c'], [30, 40, 50, 120]]
l_3 = [[1],['a', 'b'], [30, 40, 50, 60, 101, 120]]
l_rand = [l_1,l_2,l_3]
l = random.choice(l_rand)
index = len(sorted(l, key=len)[0])
l_exit = [[j for i in l for j in i[:index]], [y for x in l for y in x[index:]]]
print(f'l: {l}')
print(f'l_exit: {l_exit}')
Test Output
l: [[1, 2, 3], ['a', 'b'], [30, 40, 50, 60]]
l_exit: [[1, 2, 'a', 'b', 30, 40], [3, 50, 60]]
This question already has answers here:
Rank items in an array using Python/NumPy, without sorting array twice
(11 answers)
Closed 4 years ago.
I have a list of Numbers, say L=[50, 10, 30], and in Python I want to return a list giving the order index of each element in L, which would be this output: [2, 0, 1].
Though it seems to be a simple task, many questions on this site (here here and here for instance) focus on the other way round, meaning the index from the sorted list point of view: [1, 2, 0], which is not what I want.
Thanks,
EDIT: about repetitions, i'd like them to be counted as well (draws taken in order of appearance). [50,30,10,30] would give [3,1,0,2]
One liner:
l = [50, 30, 10, 30]
numpy.argsort(numpy.argsort(l))
# array([3, 1, 0, 2])
it is the index list of the sorted order:
def sort_order(lst):
orders = sorted(list(range(len(lst))), key=lambda x: lst[x])
ret = [0] * len(lst)
for i in range(len(ret)):
ret[orders[i]] = i
return ret
print(sort_order([50, 10, 30]) # [2,0,1]
Enumerating and sorting twice like:
L = [50, 10, 30]
x = tuple(k[1] for k in sorted((x[1], j) for j, x in enumerate(
sorted((x, i) for i, x in enumerate(L)))))
print(x)
Results:
(2, 0, 1)
Using dicts..
L = [50, 10, 30, 10, 30]
d = {counter:value for counter,value in enumerate(L)} #L is your list
sorteddict = sorted(d.items(), key=lambda x: x[1])
d2 = {counter:value for counter,value in enumerate(sorteddict)}
order_index = {d2[i][0]:i for i in d2}
print(order_index.values())
V = [[10,20,30,40],[30,40,50,-50,-70]]
V_max_result = max(V)
V_max_result_index = V.index(max(V))
print(V_max_result,V_max_result_index)
Presently, it is giving output like [30, 40, 50, -50, -70] 1
I wanted it to show something like [[40,3],[50,2]] where 40 is maximum in first list and it is located at 3.
V = [[10,20,30,40], [30,40,50,-50,-70]]
print([[max(per_v), per_v.index(max(per_v))] for per_v in V])
Output:
[[40, 3], [50, 2]]
While the answer by #atline works, it has to iterate three times over each sublist, once to get the maximum, a second time to get the maximum again and then a third time to find its position in the list.
Instead it is easier to find the maximum of tuples, where each tuple is like (value, index). This is almost what enumerate returns (index, value), just reversed. We can use zip(values, itertools.count()) for that. It works, because tuples sort by first sorting according to the first entry, then the second.
from itertools import count
V = [[10,20,30,40], [30,40,50,-50,-70]]
print([max(zip(per_v, count())) for per_v in V])
# [(40, 3), (50, 2)]
If you insist on the inner tuples being lists as well:
print([list(max(zip(per_v, count()))) for per_v in V])
# [[40, 3], [50, 2]]
Say I have a simple list of numbers, e.g.
simple_list = range(100)
I would like to shorten this list such that the gaps between the values are greater than or equal to 5 for example, so it should look like
[0, 5, 10...]
FYI the actual list does not have regular increments but it is ordered
I'm trying to use list comprehension to do it but the below obviously returns an empty list:
simple_list2 = [x for x in simple_list if x-simple_list[max(0,x-1)] >= 5]
I could do it in a loop by appending to a list if the condition is met but I'm wondering specifically if there is a way to do it using list comprehension?
This is not a use case for a comprehension, you have to use a loop as there could be any amount of elements together that have less than five between them, you cannot just check the next or any n amount of numbers unless you knew the data had some very specific format:
simple_list = range(100)
def f(l):
it = iter(l)
i = next(it)
for ele in it:
if abs(ele - i) >= 5:
yield i
i = ele
yield i
simple_list[:] = f(simple_list)
print(simple_list)
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95]
A better example to use would be:
l = [1, 2, 2, 2, 3, 3, 3, 10, 12, 13, 13, 18, 24]
l[:] = f(l)
print(l)
Which would return:
[1, 10, 18, 24]
If your data is always in ascending order you can remove the abs and just if ele - i >= 5.
If I understand your question correctly, which I'm not sure I do (please clarify), you can do this easily. Assume that a is the list you want to process.
[v for i,v in enumerate(a) if abs(a[i] - a[i - 1]) >= 5]
This gives all elements with which the difference to the previous one (should it be next?) are greater or equal than 5. There are some variations of this, according to what you need. Should the first element not be compared and excluded? The previous implementation compares it with index -1 and includes it if the criteria is met, this one excludes it from the result:
[v for i,v in enumerate(a) if i != 0 and abs(a[i] - a[i - 1]) >= 5]
On the other hand, should it always be included? Then use this:
[v for i,v in enumerate(a) if (i != 0 and abs(a[i] - a[i - 1]) >= 5) or (i == 0)]