i am trying to pick 7 numbers at random out of a list on 10, i have written the following code to help me do that :
s=set(range(1,10))
import random
i = []
while len(i)<8:
s.remove(random.choice(list(s)))
i.append(s)
print i
an important point of this is the number is removed from the group to prevent it being picked twice
however when i run the code i get the error :
Traceback (most recent call last):
File "randomTest.py", line 7, in <module>
s.remove(random.choice(list(s)))
File "/usr/lib/python2.7/random.py", line 273, in choice
return seq[int(self.random() * len(seq))] # raises IndexError if seq is empty
IndexError: list index out of range
What is causing the error and how do i fix it ?
Don't reinvent the wheel. What you are looking for is random.sample -
>>> s=set(range(1,10))
>>> import random
>>> random.sample(s,7)
[7, 5, 6, 8, 9, 3, 4]
Though this working on set actually seems like an implementation detail (and may not work for sets with more than 21 elements) because random.sample internally converts the iterable (first argument) it receives into a list at https://hg.python.org/cpython/file/c6880edaf6f3/Lib/random.py#l330. It would be better to not rely on this implementation detail and manually convert the set/sequence to a list or sequence -
>>> s=set(range(1,10))
>>> import random
>>> random.sample(list(s),7)
[6, 8, 4, 2, 5, 9, 7]
From documentation -
random.sample(population, k)
Return a k length list of unique elements chosen from the population sequence. Used for random sampling without replacement.
And as mentioned in the comments, you may not really need a set here.
You code should not produce IndexError: list index out of range, since in your example s contains 10 elements, and you choose 7.
Maybe this exception was raised while executing this code on a different set.
However, you should fix a bug that will prevent you from seeing the results you seek:
Each time, you are appending all of s into i, what you want is to append only the chosen value.
Suggestion:
s=set(range(1,10))
import random
i = []
while len(i)<8:
chosen = random.choice(list(s))
s.remove(chosen)
i.append(chosen)
print i
Related
I'm pretty new to python and I'm stacked on a simple problem:
i have a list:
mylist = [1, 2, 3, 4]
if I extract one element like this:
print(my_list[1:2])
I get a list of one element, but i cannot compute any calculus by treating it as a variable :
print(my_list[1:2]+1)
because i get the error:
Traceback (most recent call last):
File "C:\...\test_tuple.py", line XX, in <module>
print(my_list[1:2]+1)
TypeError: can only concatenate list (not "int") to list
how do I convert this single element list to a variable?
What you are doing, with :, is slicing. This means grabbing a piece of a list as a new list. What you want is just one index, which you can do be using:
mylist = [1, 2, 3, 4]
print(mylist[2]+1)
You can also turn a one element list into a variable by using:
mylist = [1, 2, 3, 4]
new_list = mylist[1:2]
print(new_list[0]+1)
Lastly you can also use numpy arrays on which you can perform calculations as if it were a normal number as follows:
import numpy as np
mylist = [1, 2, 3, 4]
new_arr = np.array(mylist[1:2])
print(new_arr[0]+1)
of course the first solution is the best in this case, but sometimes other solutions can fit your problem better.
You're error is about, you are adding number to [],
you need to add number to number like below code;
print(my_list[1:2+1])
print(my_list[2+1])
print(my_list[2]+1) ##here youre adding to the value like (my_list[2])3+1 that it will not give you error
In Python, if I want to add one element like below, what do I need to do (without using build-in-function)?
a = [0,1,2,3]
a[3+1]=4
print(a)
Traceback (most recent call last):
File "/home/cyber/Program/Python/Design Thinking/Python code/q2.py", line 18, in <module>
a[3+1]=4
IndexError: list assignment index out of range
Looks like you want to add the value 4 to the end of list a in which case:
a = [0,1,2,3]
a += [4]
print(a)
Output:
[0, 1, 2, 3, 4]
However, if you want to add a value at, say, index 5 then you can't do that without extending the list to accommodate that index and any missing ones. What are known in other languages as sparse lists (arrays) don't exist in Python. Of course you could write something yourself
I want to implement bubblesort using python list comprehension but it displays blank. Tried using assignment operators to swap (l[j]=l[j+1]) but it throws an error as list comprehension does not support assignment
l = [8, 1, 3, 5, 4, 6, 7, 2]
newlist= [ [(l[j],l[j+1]),(l[j+1],l[j])] for i in range(1,len(l)-1) for j in range(0,len(l)-1) if l[j]>l[j+1] ]
Expected output is: 1, 2, 3, 4, 5, 6, 7, 8
But I am getting the output as [].
This fails from a conceptual problem, which is that every filtered result must produce a value to include in the list. Your list comprehension has no capability to store intermediate results -- it's doomed to failure. You have to determine whether to emit a value, and which value to emit, given only the original list, i, and j. That information does not exist with bubble-sort logic.
For instance, consider the first nested iteration. You have this information at hand:
l = [8,1,3,5,4,6,7,2]
i = 1
j = 0
Given this, you must decide right now whether or not to put information into y our final list -- if so, which information to put there. You cannot defer this to a second pass, because you have no temporary storage within the comprehension.
See the problem?
I don't have a specific piece of code that I want looked at; however, I do have a question that I can't seem to get a straight, clear answer.
Here's the question: if I have a set, I can iterate over it in a for loop. As I iterate over it can I remove specific numbers using .remove() or do I have to convert my set to a list first? If that is the case, why must I convert it first?
In both cases, you should avoid iterating and removing items from a list or set. It's not a good idea to modify something that you're iterating through as you can get unexpected results. For instance, lets start with a set
numbers_set = {1,2,3,4,5,6}
for num in numbers_set:
numbers_set.remove(num)
print(numbers_set)
We attempt to iterate through and delete each number but we get this error.
Traceback (most recent call last):
File ".\test.py", line 2, in <module>
for num in numbers_set:
RuntimeError: Set changed size during iteration
Now you mentioned "do I have to convert my set to a list first?". Well lets test it out.
numbers_list = [1,2,3,4,5,6]
for num in numbers_list:
print(num)
numbers_list.remove(num)
print(numbers_list)
This is the result:
[2, 4, 6]
We would expect the list to be empty but it gave us this result. Whether you're trying to iterate through a list or a set and delete items, its generally not a good idea.
#nathancy has already given a good explanation as to why deleting during iteration won't work, but I'd like to suggest an alternative: instead of doing the deletion at the same time as you iterate, do it instead as a second stage. So, you'd instead:
Iterate over your set to decide what you want to delete, and store the collection of things to be deleted separately.
Iterate over your to-be-deleted collection and removing each item from the original set.
For instance:
def should_be_deleted(num):
return num % 2 == 0
my_set = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
to_delete = []
for value in my_set:
if should_be_deleted(value):
to_delete.append(value)
for value in to_delete:
my_set.remove(value)
print(my_set)
Prints:
set([1, 3, 5, 7, 9])
The same pattern can be applied to delete from any collection—not just set, but also list, dict, etc.
This is how I'd do this:
myset = ...
newset = set()
while myset:
v = myset.pop()
if not do_i_want_to_delete_this_value(v):
newset.add(v)
myset = newset
A list comprehension will work too:
myset = set([x for x in myset if not do_i_want_to_delete_this_value(x)])
But this gets messy if you want to do other stuff while you're iterating and you don't want to wrap all that logic in a single function call. Nothing wrong with doing that though.
myset = set([x for x in myset if process_element(x)])
process_element() just has to return True/False to say if the element should be removed from the set.
So what I have is a list of integers such as [2, 2, 2, 3, ..., n] the length of the list can be anywhere from 1 to 100. What I need to do is calculate the powers of all the numbers. This should be super easy but there is also the stipulation that you must raise each number to the power of the next number to the power of the next number and so on. FOR EXAMPLE: if the list contained [2, 3, 4] first I would need to calculate the power of 3^4 and then 2^(answer of 3^4). If the list is longer it would need to calculate the value for all of them. The example above [2, 3, 4] should return 2^81 which should be something like 2417851639229258349412352 according to wolfram. Any help would be awesome even if its just an algorithm (I can figure out the code from there) I've just been struggling to come up with a sufficient algorithm for some time now.
here is some code I have now...
temp = []
length = 0
for num in powernumbers:
for index in num:
if index.isdigit():
temp.append(index)
length = len(temp)
if length > 0:
for j in reversed(range(len(temp))):
_temp = math.pow(int(temp[j-1]), int(temp[j]))
#THE ABOVE CODE WILL ONLY WORK FOR A LIST OF LEN 2
print(_temp)
#needs math.pow(0,(math.pow(1,(math.pow(2,...)))))
print("TEMP:", temp)
Once again any help is super appreciated!
You could use functools.reduce with reversed list:
>>> from functools import reduce
>>> l = [2, 3, 4]
>>> reduce(lambda x, y: y**x, reversed(l))
2417851639229258349412352
reduce takes two arguments: function and iterable. Then it will cumulatively apply the function to reduce the iterable to single value. First parameter of the function is reduced value and second parameter is item from iterable. Since we want to process the list in reverse order we're using reversed so that 3**4 will be executed first.
Note that on Python 2 reduce is a builtin so there's no need to import anything.
>>> numbers = [2,3,4] # your list
>>> result = 1
>>> for n in reversed(numbers):
result = n**result
>>> result
2417851639229258349412352
>>>
first initialize the result on 1, then go through the list in reverse order raising the number to the previous result, which the first time is 1 resulting for this example in
result = 4**1 -> 4
result = 3**4 -> 81
result = 2**81 -> 2417851639229258349412352
but be aware, this Nested exponentials will grow very very fast, and you more likely would get a memory error for the insanely big numbers
>>> result = 1
>>> powers = [2,2,2,2,2,2]
>>> for n in reversed(powers):
result = n**result
Traceback (most recent call last):
File "<pyshell#60>", line 2, in <module>
result = n**result
MemoryError
>>>
Pop the last element off of the list, then go through the list backwards and keep exponentiating.
powernumbers = [2, 3, 4]
result = powernumbers.pop()
for num in powernumbers[::-1]:
result = num**result
The result:
>>> result
2417851639229258349412352