getting second smallest value from list - python

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))

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]]

I created a function that groups numbers from a list to a list based on their frequency and I need help optimizing it

UPDATE - I have managed to 'fix' my problem but I'm a 100% sure that this is not the optimal solution.
Also I forgot to mention that the order of each frequency group must be ordered from greatest number to least
input:
[-1,1,-6,4,5,-6,1,4,1]
output:
[[5, -1], [4, 4, -6, -6], [1, 1, 1]]
This is the updated code that I wrote:
def freqSort(nums)
#This section makes an ordered hash map that is ordered from least to greatest frequency
hash_map = {x:0 for x in nums}
hash_lst = []
for num in nums:
hash_map[num] += 1
hash_lst = sorted(hash_map.items(), key=lambda x: x[1], reverse=True)
hash_lst.reverse()
#This section creates a list of frequencies for each type of number in the list
key_lst = []
for key in hash_lst:
key_lst.append(key[1])
interval_map = {x:0 for x in key_lst}
for num in key_lst:
interval_map[num] += 1
#This section initializes an array based on the number of frequencies
array_lst = []
for num in interval_map:
array_lst.append([])
#This section appends numbers into their corresponding frequencies
i = 0
j = 0
for tup in hash_lst:
array_lst[i].append(tup[0])
if j+1 != len(key_lst):
if key_lst[j] != key_lst[j+1]:
i += 1
j += 1
k = 0
#array_lst at this point looks like [[5, -1],[4, -6],[1]]
#This section multiplies each number in each array based on the frequency it is grouped in
for interval in interval_map:
array_lst[k] = np.repeat(array_lst[k], interval)
k+=1
result_lst = []
for array in array_lst:
result_lst.append(sorted(list(array), reverse=True))
return result_lst
I've got a function called frequency, which stores the occurrence of each element in a dictionary such that element:occurrence. I use get_output to format it properly by finding the length
of the individual elements of the list and grouping them together (by using + operator).
lst = [-1,1,-6,4,5,-6,1,4,1]
def f(r): #to check if elements in the list are same
if r.count(r[0])==len(r):
return True
d={}
megalist=[]
def frequency(x):
for i in x:
d[i]=x.count(i)
for j in d:
n=d[j]
if n in d.values():
megalist.append([j for k in range(d[j])])
frequency(lst)
def get_output(y):
for a in y:
for b in y:
if a!=b:
if len(a)==len(b)and f(a) ==True and f(b)==True:
y[y.index(a)]=a+b
y.remove(b)
print(y)
get_output(megalist)
output:
[[-1, 5], [1, 1, 1], [-6, -6, 4, 4]]
UPDATE:
For this,
the order of each frequency group must be ordered from greatest number to least input
You could run a for loop and sort the individual elements of the list (using "list".sort(reverse=True))

Finding all elements greater than current element in a list

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])

IndexError: list index out of range for creating new list

I'm making a list from the previous 2 lists. I have 2 lists boxSize, item. I have to make a new list finalArray where the item are repeated boxSize times
eg boxSize = [3,2,1] & item = [1,6,4] then I want to craete the array as finalArray = [1,1,1,6,6,4]
def maxSize(boxSize, item, truckSize):
c = 0
finalArray = []
for i in range(len(boxSize)):
for j in range(boxSize[i]):
finalArray[c] = item[i]
c += 1
finalArray.sort(reverse= True)
maxi = 0
finalArray = finalArray[:truckSize]
for i in range(truckSize):
maxi += maxi + finalArray[i]
return maxi
The error I'm getting is IndexError: list index out of range at finalArray[c] = item[i]
You should use append for this particular case as the list at inital level is empty
def maxSize(boxSize, item, truckSize):
c = 0
finalArray = []
for i in range(len(boxSize)):
for j in range(boxSize[i]):
finalArray.append(item[i])
finalArray.sort(reverse= True)
maxi = 0
finalArray = finalArray[:truckSize]
for i in range(truckSize):
maxi += maxi + finalArray[i]
return maxi
A much cleaner way of doing this:
from itertools import starmap, repeat
boxSize = [3,2,1]; item = [1,6,4]
smap = starmap(repeat, zip(item, boxSize))
output = [n for rep in smap for n in rep]
>>>output
[1, 1, 1, 6, 6, 4]
Zip pairs together item and boxSize (pairwise).
Repeat is applied to each zip. So the first element of each pair is repeat the number of time specified by the second element of each pair.
Starmap applies repeat to the pairs.
you can use list comprehension
CODE:
print([x for x,y in zip(item, boxSize) for _ in range(y)])
OUTPUT:
[1, 1, 1, 6, 6, 4]
EXPLANATION:
repeat x (from item) y (from boxSize) times
Have a look into these built-ins:
zip
range
and this data structure:
list comprehension
or if you want to use a for loop, for improved readability
CODE:
res = []
for n,x in enumerate(boxSize):
res.extend([item[n]]*x)
print(res)
OUTPUT:
[1, 1, 1, 6, 6, 4]
EXPLANATION:
get the index (n) and the value (x) of each element in boxSize. for each n, x couple, generate a list with x repetition of the nth element in item list and extend res with the result
Have a look at this built-in:
enumerate
this (operation on) data structures:
enumerate
and check the result of:
[42]*3
The problem here is that you start by creating a list finalArray: [] which is an empty, hence, no index-value can be called or adressed. In your nested for loops you are trying to address the first value of your list and make it equal to a given value in array item. This is impossible since as we said before, finalArray is an empty list can has no index-value that can be passed. If you wish to add values to the list that will the equal the index value of c then you should use append. Here's a solution:
import itertools
box = [3,2,1]
item = [1,6,4]
supportarray = []
finalarray = []
s_item = [str(x) for x in item]
for i in range(len(s_item)):
supportarray.append(s_item[i]*box[i])
for i in range(len(supportarray)):
finalarray.append([int(f) for f in supportarray[i]])
finalarray = list(itertools.chain.from_iterable(finalarray))
print(finalarray)
Output: [1,1,1,6,6,4]

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