python the multiple largest numbers in a list - python

import random as rd
ListNumbers1 = []
List1 = []
for j in range(1000):
ListNumbers1 = rd.randint(1,10000)
How would i get the 50 highest numbers from ListNumbers1 and append to list1?

Something like this?
List1.extend(sorted(ListNumbers1)[-50:])

You're assigning the same value over and over in your loop, destroying your list in the process. Use append...
Better: create a list comprehension of the numbers, then use heapq.nlargest to directly get the 50 highest numbers:
import random as rd
import heapq
highest_50 = heapq.nlargest(50,[rd.randint(1,10000) for _ in range(1000)])
print(highest_50)
a result:
[9994, 9983, 9983, 9968, 9934, 9925, 9913, 9912, 9909, 9909, 9902, 9889, 9884, 9880, 9811, 9794, 9793, 9792, 9765, 9756, 9750, 9748, 9738, 9737, 9709, 9707, 9704, 9700, 9691, 9686, 9635, 9618, 9617, 9605, 9604, 9593, 9586, 9584, 9573, 9569, 9569, 9557, 9531, 9528, 9522, 9438, 9438, 9431, 9402, 9400]

Just for fun, I have a more efficient solution:
from random import randint
import heapq
# create a list of 1000 random numbers
# take the negative, so the min heap does what we want
dataset = [-randint(1, 10000) for _ in range(1000)]
# O(n) function to impose the heap invariant
heapq.heapify(dataset)
# sorting is O(n log n)
# extracting from a heap is log n per item
# therefore taking the 50 biggest is much more efficent if
# we use a heap to extract only the ones we need
top50 = [-heapq.heappop(dataset) for _ in range(50)]
print top50
This is a faster solution because the 50 you want to extract is much less than the 1000 total input size. I renamed the variables, but that's just my personal preference.

Like that (notice how assigning random number is fixed):
import random as rd
ListNumbers1 = []
List1 = []
for j in range(1000):
ListNumbers1.append(rd.randint(1,10000)) # fix: append each random element
ListNumbers1.sort() # sort the list, ascending order
List1 = ListNumbers1[-50:] # get last 50 elements of the list and assign it to List1

To search for the n biggest numbers in a list you need two procedures: one to find the biggest, the other to extract the n biggest.
You could also sort the list and take the n first, but this is not my approach because I needed to keep the original list and study it as is. For example, you could also know the offsets of each chosen number, which could be useful in some case.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
def n_biggest(lis,howmany):
#this function returns the biggest of a list with its offset
def biggest_in_list(lis):
n=0
biggest=0
offset=0
for item in lis:
n=n+1
if (item>biggest):
biggest=item
offset=n-1
return[biggest,offset]
#now this is the part where we create the descending list
image=lis#the use of an image will prevent finding twice the same number
result_list=[]
if len(lis)<howmany:#this will prevent errors if list is too small
howmany=len(lis)
for i in range(howmany):
find1=biggest_in_list(image)
result_list.append(find1[0])
image.pop(find1[1])
return result_list
print n_biggest([5,4,6,10,233,422],3)#this line was for testing the above
Hope this helps,
Regards,

import random as rd
List1 = sorted([rd.randint(1,10000) for j in range(1000)])[-50:]
Slice the last 50 elements of a sorted list comprehension, then you don't need ListNumbers1

Related

How to get items from a list > than X

I have a function called "first_funtion()" that returns a list of 100 instances of a class.
Then I want to define a second function that is going to create a new list with random instances taken from the output list of first_function(), something like:
first_funtion()
def second_function(list2, N):
list2 = list2(random.choice(first_function()))
The thing is that I want list2 to be always greater than N, so if N = 5 I want the random list2 to be more than 5 instances. If N = 10 then I want the list to be more that 10 instances.
How can I do that?
You can first create the list using first_function, then draw a random integer in the range between N and the length of the list and then draw a random sample from the list.
import random
def second_function(list2, N):
len_list = len(list2)
length = random.randint(N, len_list)
return random.sample(list2, length)
You can do it by using two random function;
Use first one to choose a value of N from the range excluding N to including lenght of list1, i.e, (N, len(list1)]
x = random.randint(N+1, len(list1)
And use second one to choose x number of values from list_1;
random.choices(list1, k=x)
So, the code will look something like this:
import random
def second_function(list1, N):
x = random.randint(N+1, len(list1))
y = random.choices(list1, k=x)
print(y)
Here randint(start, stop) includes both start and stop numbers while generating random integer. It will generate a random number from the inclusive range.
Andrandom.choices () function returns total k number of random items from any list.
Note: You may get repeated values if you're using random.choices (). So, use random.sample() function when you want to choose multiple random items from a list without repetition or duplicates.
You can visit on this link and explore more related to this.
As the random.choice() function always picks one element from the list, so you can iterate through the list more than N number of times and use random.choice() each time. And you can also use random.randint() to get a random number above N, to be used in the range function for the for loop.
import random
def second_function(list2, N):
for i in range(N,random.randint(N,len( first function() ))) :
list2.append(random.choice(first_function()))
return list2

Large list generation memory managment

import itertools
Num = 11
base = list(range(1,Num+1))
Permutations = list(itertools.permutations(base))
I'm getting a memory error trying to run this. In reality I only need to generate the 1st (Num-1)! permutations but I'm not sure how to (so if Num = 7 i would need to generate the first 6! = 720 permutations). But I would ideally like to be able to generate permutations for significantly higher values of Num so any suggestions would be great
range() and permutation() both return generators that generate items on demand. You don't need to call list() and turn them into lists. Just iterate over them directly and access the items one by one.
num = 11
base = range(1, num+1)
permutations = itertools.permutations(base)
for permutation in permutations:
# Do something with `permutation`.
(Note that a generator can only be used once. If you want to iterate over the permutations more than once you'll need to call itertools.permutations() multiple times.)
To stop after n items use itertools.islice():
for permutation in itertools.islice(permutations, n):
# Do something with `permutation`.
You can skip items at the beginning, too. This would skip the first five permutations:
for permutation in itertools.islice(permutations, 5, n):
# Do something with `permutation`.
If you want to count the permutations you can add enumerate(), which attaches an index to every entry:
for i, permutation in enumerate(itertools.islice(permutations, n)):
# Skip the fifth permutation.
if i == 4:
continue
# Do something with `permutation`.
By the way, please use lowercase for variable names. Only class names should be capitalized.

How to take a number out of a list and put on another list

I have some code that creates a list with numbers, from 1 to 561. I want to create a variable that is called "ultimate" that has 45 of those values, but, the ones that I put on that list, I want it to be removed from the cards_id list. How can I do that? This is the general code I have.
def cards_id(x):
list = []
for i in range(1,x+1):
list.append(i)
return list
cards_id(561)
import random
print (random.choice(cards_id(561)))
from random import shuffle
for i in range(0,45):
print (random.choice(cards_id(561)))
No need to iterate, append cards to a new list and remove cards from the original one (very inefficient).
You may just shuffle the original list and take the first 45 elements, while changing the original list to take the remaining ones.
cards = list(range(1,562))
random.shuffle(cards)
selected, cards = cards[:45], cards[45:]
You can use numpy :
import numpy as np
cards_id = np.arange(561) + 1
ultimate = np.random.choice(cards_id, 45)
cards_id = np.setdiff1d(cards_id, ultimate)
You can do it like this:
def cards_id(x):
lis = []
for i in range(1,x+1):
lis.append(i)
return lis
import random
cards_id_list=cards_id(561)
ultimate=[]
for i in range(0,45):
a=random.choice(cards_id_list)#random element from the list
ultimate.append(a)
cards_id_list.remove(a)#remove from the list here

How to get the position of a random number generated in a python list.?

I have a numeric list. I need pick a random number in a numeric list and know position number found in list.
random.choice(name_list) just find a random number but I am at the same time in need of a random number position
generate random indexes to use instead.
import random
a = [1,2,3,4,5]
rand_num = random.randrange(len(a))
print(a[rand_num])
You could also get the index and the random number in one operation using enumerate()
index,number = random.choice(list(enumerate(a)))
This not very efficient however and, if you're doing this often or on a very big list, you should do it in two steps
index = random.randrange(len(a))
number = a[index]
import random
sample_list = [1,2,3,4,5]
# this should be work for multiple same value indexes
# EX: sample_list = [1,2,3,2,2]
# if random number is 2 than below code will print indexes 1, 3, 4
random_number = random.choice(sample_list)
for i in [i for i,x in enumerate(sample_list) if x == random_number]:
print(i) # print the indexes or random number

Getting the first elements of a dictionary without using a loop

I have this piece of code and was wondering if there was any inbuilt way to do it faster?
Words has a simple tokenized string input.
freq_unigrams = nltk.FreqDist(words)
unigram_list = []
count = 0
for x in freq_unigrams.keys():
unigram_list.append(x)
count+=1
if count >= 1000:
break
Does freq_unigrams.keys() return a list? If so, how about the following:
unigram_list = freq_unigrams.keys()[:1000]
This gives you a list containing the first 1000 elements of freq_unigrams.keys(), with no looping.
I suggest:
unigram_list = freq_unigrams.keys()
unigram_list[:] = unigram_list[:1000]
This would not make the copy that: unigram_list = freq_unigrams.keys()[:1000] does.
Although this might be better with iterators:
from itertools import islice
unigram_list[:] = islice(freq_unigrams.iterkeys(),1000)
If your intent is to get the top 1000 most frequent words in the words list you could try:
import collections
# get top words and their frequencies
most_common = collections.Counter(words).most_common(1000)
This is theoretically more efficient:
import itertools
unigram_list = list(itertools.islice(freq_unigrams.iterkeys(), 1000))
...than working off freq_unigrams.keys(), because you're only interested in the top 1000, and not the remaining x, which the using freq_unigrams.keys() will also need to populate in the intermediate list.
**a little late...
To take the first 1000 keys in your dictionary and assign them to a new list:
unigram_list = freq_unigrams.keys()[:1000]

Categories