Finding all elements greater than current element in a list - python

If I have an array in Python in which all of the elements have different values, e.g. [1,4,6,2,10,3,5],
is there a way to find the total number of values in the list that are greater than the current index?
So for example, using the above list of length 7, the result I'd like to get is another list of length 7 which looks like [6,3,1,5,0,4,2]. I was having trouble trying to loop through the list (the code I tried to use is below)
for i in data:
count = np.sum(data > data[i])
N[i]=count
where data is the array containing all the pertaining values and N is an np.zeros list of the same length as data

You were very close. for i in data iterates through each element, not the indices as in Java/C.
Use range(len(data)) instead.
import numpy as np
data = np.array([1,4,6,2,10,3,5])
out = np.array([0]*7)
for i in range(len(data)):
count = np.sum(data > data[i])
out[i] = count
print(out) # [6 3 1 5 0 4 2]
Another way to write the loop is to use enumerate(), which returns an iterator of pairs of (indices, elements).
for i, x in enumerate(data):
count = np.sum(data > x)
out[i] = count

Here is my suggestion:
We sort the original list (l) and save it in a new list m. We create a new list (k) where we save the count of elements that are found on the right of the position of each element in m. See below:
l=[1,4,6,2,10,3,5]
m=sorted(l)
#[1, 2, 3, 4, 5, 6, 10]
k=[]
for i in l:
k.append(len(m)-m.index(i)-1)
>>> print(k)
[6, 3, 1, 5, 0, 4, 2]

Something like this?
list = [1,4,6,2,10,3,5]
list2 = []
v = len(list)
for x in list:
if x > v:
pass
else:
list2.append(x)
print(list2)
EDIT ¯\_(ツ)_/¯ (To see the total number of elements greater than the current element)
list = [1,4,6,2,10,3,5]
list2 = []
v = len(list)
total = 0
for x in list:
if x > v:
pass
else:
list2.append(x)
for y in list2:
total += 1
list2 = str(list2).replace('[', '')
list2 = list2.replace(']', '')
print("Now - " + list2 + ", in total of " + str(total) + " numbers ;)")
Output -
Now - 1, 4, 6, 2, 3, 5, in total of 6 numbers ;)

Alternatively, you can do it by using vectorize as follows:
>>> data = np.array( [1,4,6,2,10,3,5] )
>>> np.vectorize(lambda a, b : np.sum(a>b), excluded = [0] )(data, data)
array([6, 3, 1, 5, 0, 4, 2])

Related

Loop to select specific numbers from a given list

My problem is that in python i have a list of 1000 numbers. I want to select first 20 and store in "A" (another list) and next 30 in "B"(another list), again next 20 in "A", next 30 in "B" untill the list ends. How to do that? Can anyone help please?
You could use two nested list comprehension for this:
nums = list(range(2000))
A = [x for i in range( 0, len(nums), 50) for x in nums[i:i+20]]
B = [x for i in range(20, len(nums), 50) for x in nums[i:i+30]]
That means (for A): Starting at index 0, 50, 100 etc., take the next 20 elements and add them to A. Analogous for B. You might also use itertools.islice for the nums[i:i+n] part to avoid creating a bunch of temporary sub-lists.
Of course, this assumes that A and B do not already exist. If they do, and you want to add elements to them, use a regular loop and extend (not tested):
for i in range(0, len(nums), 50):
A.extend(nums[i :i+20])
B.extend(nums[i+20:i+50])
You do not have to check the indices again within the loop; if i+20 is already bigger than the last index in the list, B will just get extended with the empty list in the last step.
I made a function that can do what you're asking
def split_list(lst, gap1, gap2):
tmp = lst.copy()
out1, out2 = [], []
while tmp:
out1.extend(tmp[:gap1])
tmp = tmp[gap1:]
out2.extend(tmp[:gap2])
tmp = tmp[gap2:]
return out1, out2
gap1 and gap2 are the length of each subset you want to store, so in your case gap1=20 and gap2=30.
Example
numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
A, B = split_list(numbers, 2, 3)
print(A)
print(B)
Let's first define the followings:
A = [] #empty list
B = [] #empty list
And let's call your first list (that includes 1000 numbers), as my_list.
Then, a simple solution can be as following:
counter = 0
c_a = 2
c_b = 3
while (counter < len(my_list)):
A = A + my_list[counter:counter+c_a]
B = B + my_list[counter+c_a : counter + c_a + c_b]
counter = counter + c_a + c_b
I suggest generating a 2D nested list, which contains sublists each having 20 elements in it. Here is a one line way of doing that with a list comprehension:
x = range(1, 1001)
output = [x[idx*20:(idx*20 + 20)] for idx in range(0, len(x) / 20)]
Here is a version which operates on a smaller set of data, for demonstration purposes:
x = [1, 2, 3, 4, 5, 6, 7, 8, 9]
output = [x[idx*3:(idx*3 + 3)] for idx in range(0, len(x) / 3)]
print(output) # [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

Change the position of the value in my list

Im trying to find a way to change the order of my list at the end.
For example, for a list of 4 boxes, we invert the values ​​of boxes 1 and 2 and we reverse the values ​​of boxes 3 and 4.
normal_list([1, 2, 3, 4]) I want the first number to be even and the second to be odd like this :
[2, 1, 4, 3]
creating an empty list
lst = []
# number of elemetns as input
n = int(input("Enter an even number: "))
if (n % 2) == 0:
print("Enter the desired",n, "numbers : ".format(n))
else:
print("Please enter an even number")
# iterating till the range
for i in range(0, n):
if n % 2 == 0:
ele = int(input())
lst.append(ele) # adding the element
else :
break
print('this is the list : ',lst)
def Split(mix):
ev_li = []
od_li = []
for i in mix:
if (i % 2 == 0):
ev_li.append(i)
else:
od_li.append(i)
print("This is the new list:", ev_li + od_li)
mix = lst
Split(mix)
There are many ways to do this. You can loop over pairs of indexes by zipping a range() iterator. This will allow you to swap the values in place:
l = [1, 2, 3, 4]
e = iter(range(len(l)))
for a, b in zip(e, e): # pairs of indexes like (0, 1), (2, 3)...
l[a], l[b] = l[b], l[a]
print(l)
# [2, 1, 4, 3]
Alternatively, you could make a new list with a list comprehension by zipping the list with itself into pairs and then reversing the pairs:
l = [1, 2, 3, 4]
new_l = [n for pair in zip(l[::2], l[1::2]) for n in reversed(pair)]
print(new_l)
# [2, 1, 4, 3]
The behavior is not really specified when the list is not an even length.
#Mark Meyer has given a terrific answer, but here are a couple of the alternatives he spoke of:
A very explicit swapper:
l = [1, 2, 3, 4]
for p in range(0,len(l),2):
l[p],l[p+1]=l[p+1],l[p]
print (l)
And the truly awful:
l = [1, 2, 3, 4]
l = [l[p^1] for p in range(len(l))]
print (l)
I leave it to the reader to figure out that last one.
You can loop through an even list and an odd list at once using zip() to do this.
old_list = [1,2,3,4,5,6]
# Make empty list of same length
new_list = []
even = []
odd = []
for item in old_list:
# Check if even
if item % 2 == 0:
even.append(item)
else:
odd.append(item)
# Loop through both lists at once
for e, o in zip(even, odd):
# add the even item first
new_list.append(e)
# then add the odd
new_list.append(o)
print(new_list) # Returns: [2,1,4,3,6,5]

Add items in a list until their sum exceeds a threshold

From a list of values I want to create a new list of values until they add up a value.
I am new with Python but I believe it is best done with a while loop.
L = [1,2,3,4,5,6,7,8,9]
i = 0
s = 0
while i < len(L) and s + L[i] < 20:
s += L[i]
i += 1
numpy arrays make this simple
import numpy as np
arr = np.array(L)
arr[arr.cumsum() <= 20].tolist()
#[1, 2, 3, 4, 5]
Since you tagged Pandas:
pd.Series(L, index=np.cumsum(L)).loc[:20].values
Output:
array([1, 2, 3, 4, 5], dtype=int64)
You first create the empty list, and then append values with the same conditions you stated. Finally printing the list will return you the values that got added that match your criteria:
L = [1,2,3,4,5,6,7,8,9]
i = 0
s = 0
new_list = []
while i < len(L) and s + L[i] < 20:
new_list.append(L[i])
s += L[i]
i += 1
print(new_list)
Output:
[1, 2, 3, 4, 5]
You can easily write your own generator function:
L = [1,2,3,4,5,6,7,8,9]
def takeuntil(lst, max_value = 0):
"""Yields elements as long as the cummulative sum is smaller than max_value."""
total = 0
for item in lst:
total += item
if total <= max_value:
yield item
else:
raise StopIteration
raise StopIteration
new_lst = [item for item in takeuntil(L, 20)]
print(new_lst)
Which yields
[1, 2, 3, 4, 5]
If you would sum from start to end the (imo) more pythonic way would be
s = 0
for element in L:
if s + element < 20:
s += element
else:
break
If we’re talking pythonic, a for loop makes more sense (also using better variable names):
data = [1,2,3,4,5,6,7,8,9]
filtered = []
for num in data:
if num < 20:
filtered.append(num)
But a comprehension is also pythonic and shorter:
filtered = [num for num in data if num < 20]
Then to get the sum just use the sum function:
total = sum(filtered)
Or if you only need the sum:
total = sum(n for n in data if n < 20)

getting second smallest value from list

x = [[1,2,3,4],[4,5,0,1],[22,21,31,10]]
def minFor(x):
removingvalue = []
for i in x:
minvalue = i[0]
for j in i:
if j < minvalue:
minvalue=j
for i in range(0,len(x)):
if x==minvalue:
removingvalue = removingvalue + minvalue
return minvalue
print(minvalue)
what I 'm trying to do here is first find the smallest number from the list. And remove that smallest value and find again the smallest number from the list. But the remove function doesn't work
This finds second smallest of each sublists in the list:
lst = [[1,2,3,4],[4,5,0,1],[22,21,31,10]]
print([sorted(x)[1] for x in lst])
# [2, 1, 21]
You just needed to sort sublist in ascending order and select second value out. There is no need of removing value from list.
Personally, I'd use the builtin sorted function:
def second_min(x):
result = []
for sublist in x:
result.extend(sublist)
# this flattens the sublists
# into a single list
result = sorted(result)
return result[1]
# return the second element
And without the built-ins, replace the sorted() call with:
...
for i in range(len(result) - 1):
if result[i] > result[i + 1]:
result[i:i + 2] = [result[i + 1], result[i]]
...
Use min(iterable) and a list comprehension to get the overall minimal value.
Then use min on the same list comp with a twist: only allow values in the second list comp that are bigger then your minimal min-value:
xxxx = [[1,2,3,4],[4,5,0,1],[22,21,31,10]]
minmin = min((x for y in xxxx for x in y)) # flattening list comp
secmin = min((x for y in xxxx for x in y if x >minmin))
print(minmin,secmin)
Output:
0 1
You can convert the given data-structure, to a single list and then sort the list. The first two elements give you the answer you want. Here's what you can do:
input_list = x
new_l = []
for sl in input_list:
new_l.extend(sl)
new_l.sort()
# First two elements of new_l are the ones that you want.
remove_smallest = [sorted(i)[1:] for i in x]
get_smallest = [min(i) for i in remove_smallest]
print(remove_smallest)
print(get_smallest)
[[2, 3, 4], [1, 4, 5], [21, 22, 31]]
[2, 1, 21]
Expanded loops:
remove_smallest = []
for i in x:
remove_smallest.append(sorted(i)[1:])
get_smallest = []
for i in remove_smallest:
get_smallest.append(min(i))

How to find unique elements in a list in python? (Without using set)

Write a function that accepts an input list and returns a new list
which contains only the unique elements (Elements should only appear
one time in the list and the order of the elements must be preserved
as the original list. ).
def unique_elements (list):
new_list = []
length = len(list)
i = 0
while (length != 0):
if (list[i] != list [i + 1]):
new_list.append(list[i])
i = i + 1
length = length - 1
'''new_list = set(list)'''
return (new_list)
#Main program
n = int(input("Enter length of the list: "))
list = []
for i in range (0, n):
item = int(input("Enter only integer values: "))
list.append(item)
print ("This is your list: ", list)
result = unique_elements (list)
print (result)
I am stuck with this error:
IndexError: list index out of range
This is the simplest way to do it:
a = [1, 2, 2, 3]
b = []
for i in a:
if i not in b:
b.append(i)
print (b)
[1, 2, 3]
The problem with your code is that you are looping length times but checking list[i] with list[i+1], thus accessing an element past the end of the input list (e.g. in a list with 6 elements there are 6-1=5 pairs of consecutive elements).
A second issue with your code is that an input with only one element [1] should give as output [1] even if this element is not different from any other. The input text means you should remove elements that are equal to other elements already present, not that you should keep elements that are different from the next one.
Another issue is that you're only checking for consecutive duplicates i.e. given the input list [1, 2, 1, 2] your logic wouldn't detect any duplication... looks like the exercise instead requires in this case as output of [1, 2].
A trace for a simple algorithm to do this is
for each element in input
if the element has not been included in output
add the element to the end of output
Note also that to check if an element is present in a list Python provides the in operator (e.g. if x in output: ...) that can save you an explicit loop for that part.
As a side note naming an input parameter list is considered bad practice in Python because list is the name of a predefined function and your parameter is hiding it.
O(n) solution without using a set:
>>> from collections import Counter, OrderedDict
>>> class OrderedCounter(Counter, OrderedDict):
... pass
...
>>> lst = [1, 2, 2, 3, 4, 5, 4]
>>> [x for x,c in OrderedCounter(lst).items() if c==1]
[1, 3, 5]
One line implementation:
list = [100, 3232, 3232, 3232, 57, 57, 90]
new_list = []
[new_list.append(x) for x in list if x not in new_list]
print(new_list)
Prints:
[100, 3232, 57, 90]
The problematic line is > if (list[i] != list [i + 1]): < (6th line in your code).
Reason:
Imagine your list has got 4 elements.
Eg: mylist = [ 1, 2,2,3].
mylist[i] != mylist [i + 1]
In the last iteration 'i' will be 4 , so i + 1 will be 5.
There is no such 5th index in that list, because list indexes are counted from zero.
mylist[0] = 1
mylist[1] = 2
mylist[2] = 2
mylist[3] = 3
mylist[4] = No Index
mylist[5] = No Index
def unique_elements (list):
new_list = []
# Replace the while with a for loop**
for i in list:
if i not in new_list:
new_list.append(i)
return (new_list)
#Main program
n = int(input("Enter length of the list: "))
list = []
for i in range (0, n):
item = int(input("Enter only integer values: "))
list.append(item)
print ("This is your list: ", list)
result = unique_elements (list)
print (result)
l = [1, 2, 2, 3,4,5,6,5,7,8]
myList = []
[ myList.append(item) for item in l if item not in myList]
print(myList)
Use of collections is best IMO,
Accepted answer is simplest,
Adding another approach using dict where you can check frequency as well,
text = [100, 3232, 3232, 3232, 57, 57, 90]
# create empty dictionary
freq_dict = {}
# loop through text and count words
for word in text:
# set the default value to 0
freq_dict.setdefault(word, 0)
# increment the value by 1
freq_dict[word] += 1
unique_list = [key for key,value in freq_dict.items()]
print(unique_list )
print(freq_dict )
[100, 3232, 57, 90]
{100: 1, 3232: 3, 57: 2, 90: 1}
[Program finished]
You can also print by values based on requirements.
So if you are at the last element, then if (list[i] != list [i + 1]): will try to take a value out of the list which is not present there and that is why the error is showing that the list is out of range.
You can work this out using sets and set comprehension syntax is in most cases overlooked. Just as lists sets can also be generated using comprehension.
elements = [1, 2, 3, 3, 5, 7, 8, 7, 9]
unique_elements = {element for element in elements}
print(unique_elements)
Found an easier approach for people on Python 3.7.
Using a dictionary:
list(dict.fromkeys(mylist))

Categories