My program should get a random name from a list every time a key is pressed, and then delete that name from the list. With the code I have now a random name is selected, but the list is emptied completely.
I have tried both a for and a while loop, but I'm uncertain as what to use in this situation.
x = win.getKey()
while len(members) > 0:
if x:
name = random.choice(members)
members.remove(name)
As mentioned above I want to draw a random name and delete that name from the list every time a key is pressed, until the list is empty.
You'll need to put your key prompt in the loop to cause the loop to pause and wait for input for each element, otherwise the loop will run to completion and instantly empty the entire list.
import random
members = [1,2,3,4,5,6,7,8,9]
while members:
if win.getKey():
choice = random.choice(members)
members.remove(choice)
print(choice)
Output:
8
4
2
3
7
6
9
5
1
If the list is very large, remove is a slow linear operation that needs to inspect each element in the list one by one to find a match. Consider using a fast (amortized) constant time pop operation which uses an index to find the target element without searching:
import random
members = [1,2,3,4,5,6,7,8,9]
while members:
if win.getKey():
choice = members.pop(random.randint(0, len(members) - 1))
print(choice)
Related
I want to randomly select an item from a list. But the twist is that the higher index an element in the list possesses, the most likely it will be chosen. And after randomly choosing an item in the list, I would like to store that item into a variable named link.
I haven't tried a lot of different ways, since I don't know where to start. But this is what I currently have:
import random
# A list of Youtube links ( I won't show the YT links )
links = ['link1 :D',
'link2 :D',
'link3 :D'
]
link = random.choice(links)
With the code above, I only get a random ( or pseudorandom ) result from an item in the links variable. How can I write the code so that it has a higher of choosing ( but still randomly ) the items with a larger index?
In case I'm not being clear, here is an example:
# List of 3 links
links = ['link1', # index: 0
'link2', # index: 1
'link3' # index: 2]
Since link3 has the highest index of 2, it has the highest possibility of being selected by a random selector. link2 has the second-highest index, so it has more chances of being selected than link1, but fewer chances of being selected than link3.
New in Python 3.6. For the previous Python version see here.
You can use the weights or cum_weights parameter in random.choices() to select according to the relative weights.
Since you want a higher change of selection for elements present at higher index, you can make your weights index based.
weights = [i for i in range(1, len(links) + 1)]
Internally, the relative weights(weights) are converted to cumulative weights(cum_weights) before making selections.
random.choices(links, weights=weights)
Note: If a weights sequence is supplied, it must be of the same length as the sample sequence.
I have just started learning python and i have been given an assignment to create a list of players and stats using different loops.
I cant work out how to create a function that searches the player list and gives an output of the players name and the players stat.
Here is the assignment:
Create an empty list called players
Use two input() statements inside a for loop to collect the name
and performance of each player (the name will be in the form of a
string and the performance as an integer from 0 – 100.) Add both
pieces of information to the list (so in the first iteration of the
loop players[0] will contain the name of the first player and
players[1] will contain their performance.) You are not required to
validate this data.
Use a while loop to display all the player information in the
following form:
Player : Performance
Use a loop type of your choice to copy the performance values from
the players list and store these items in a new list called results
Write a function that accepts the values “max” or “min” and
returns the maximum or minimum values from the results list
Write a function called find_player() that accepts a player name
and displays their name and performance from the players list, or an
error message if the player is not found.
Here is what I have so far:
print ("Enter 11 Player names and stats")
# Create player list
playerlist = []
# Create results list
results = []
# for loop setting amount of players and collecting input/appending list
for i in range(11):
player = (input("Player name: "))
playerlist.append(player)
stats = int(input("Player stats: "))
playerlist.append(stats)
# While loop printing player list
whileLoop = True
while whileLoop == True:
print (playerlist)
break
# for loop append results list, [start:stop:step]
for i in range(11):
results.append(playerlist[1::2])
break
# max in a custom function
def getMax(results):
results = (playerlist[1::2])
return max(results)
print ("Max Stat",getMax(results))
# custom function to find player
def find_player(playerlist):
list = playerlist
name = str(input("Search keyword: "))
return (name)
for s in list:
if name in str(s):
return (s)
print (find_player(playerlist))
I have tried many different ways to create the find player function without success.
I think I am having problems because my list consists of strings and integers eg. ['john', 6, 'bill', 8]
I would like it to display the player that was searched for and the stats ['John', 6]
Any help would be greatly appreciated.
PS:
I know there is no need for all these loops but that is what the assignment seems to be asking for.
Thank you
I cut down on the fat and made a "dummy list", but your find_player function seems to work well, once you remove the first return statement! Once you return something, the function just ends.
All it needs is to also display the performance like so:
# Create player list
playerlist = ["a", 1, "b", 2, "c", 3]
# custom function to find player
def find_player(playerlist):
name = str(input("Search keyword: "))
searchIndex = 0
for s in playerlist:
try:
if name == str(s):
return ("Player: '%s' with performance %d" % (name, playerlist[searchIndex+1]))
except Exception as e:
print(e)
searchIndex += 1
print (find_player(playerlist))
>>Search keyword: a
>>Player: 'a' with performance 1
I also added a try/except in case something goes wrong.
Also: NEVER USE "LIST" AS A VARIABLE NAME!
Besides, you already have an internal name for it, so why assign it another name. You can just use playerlist inside the function.
Your code didn't work because you typed a key and immediately returned it. In order for the code to work, you must use the key to find the value. In this task, it is in the format of '' key1 ', value1,' key2 ', value2, ...]. In the function, index is a variable that stores the position of the key. And it finds the position of key through loop. It then returns list [index + 1] to return the value corresponding to the key.
playerlist = []
def find_player(playerlist):
list = playerlist
name = str(input("Search keyword: "))
index = 0
for s in list:
if name == str(s):
return ("This keyword's value: %d" % (list[index+1]))
index+=1
print (find_player(playerlist))
I have been set a task, to using an original Dataset of 25 A's and C's (50 data points in total), to randomly select 1 of the 50 data points then add this to a new nested list and to repeat this 50 times (length of dataset). This random selection then needs to be done again with the new dataset, for 25 times.
import random
SetSize = 50
StatData = [[] for b in range(1,50)]
for i in range(0, int(SetSize/2)):
StatData[0].append('A')
for i in range(int(SetSize/2)):
StatData[0].append('C')
for a in range(1,25):
for b in range(0, int(SetSize)):
StatData(a+1).append(random.choice(StatData[a]))
This is my current piece of code, so i have created the empty nested list, created the initial dataset (StatData0) however the next section is not working it is returning
"TypeError: 'list' object is not callable"
Any help would be much appreciated!
The error says it all. You cannot call a list.
Typo
On the last line of the code you provided, change
StatData(a+1).appen...
to
StatData[a+1].appen...
and I guess it should fix the error.
Index problem (edit)
You are populating the list of index 0 with As and Bs (StatData[0]) but in your last loop a goes from 1 to 50. So your first iteration will choose a random character in StatData[1] (which is empty) thus throwing another error.
Starting your loop from the index 0 should make this go away !
total=0
line=input()
line = line.upper()
names = {}
(tag,text) = parseLine(line) #initialize
while tag !="</PLAY>": #test
if tag =='<SPEAKER>':
if text not in names:
names.update({text})
I seem to get this far and then draw a blank.. This is what I'm trying to figure out. When I run it, I get:
ValueError: dictionary update sequence element #0 has length 8; 2 is required
Make an empty dictionary
Which I did.
(its keys will be the names of speakers and its values will be how many times s/he spoke)
Within the if statement that checks whether a tag is <SPEAKER>
If the speaker is not in the dictionary, add him to the dictionary with a value of 1
I'm pretty sure I did this right.
If he already is in the dictionary, increment his value
I'm not sure.
You are close, the big issue is on this line:
names.update({text})
You are trying to make a dictionary entry from a string using {text}, python is trying to be helpful and convert the iterable inside the curly brackets into a dictionary entry. Except the string is too long, 8 characters instead of two.
To add a new entry do this instead:
names.update({text:1})
This will set the initial value.
Now, it seems like this is homework, but you've put in a bit of effort already, so while I won't answer the question I'll give you some broad pointers.
Next step is checking if a value already exists in the dictionary. Python dictionaries have a get method that will retrieve a value from the dictionary based on the key. For example:
> names = {'romeo',1}
> print names.get('romeo')
1
But will return None if the key doesn't exist:
> names = {'romeo',1}
> print names.get('juliet')
None
But this takes an optional argument, that returns a different default value
> names = {'romeo',2}
> print names.get('juliet',1)
1
Also note that your loop as it stands will never end, as you only set tag once:
(tag,text) = parseLine(line) #initialize
while tag !="</PLAY>": #test
# you need to set tag in here
# and have an escape clause if you run out of file
The rest is left as an exercise for the reader...
for all the strings in a list of strings, if either of the first two characters of the string match (in any order) then check if either of last two strings match in specific order. If so, I will ad an edge between two vertex in graph G.
Example:
d = ['BEBC', 'ABRC']
since the 'B' in the first two characters and the 'C' in the second two characters match, I will add an edge. I'm fairly new to Python and what I have come up with through previous searches seems overly verbose:
for i in range(0,len(d)-1):
for j in range(0,len(d)-1):
if (d[i][0] in d[j+1][:2] or d[i][1] in d[j+1][:2]) and \
(d[i][2] in d[j+1][2] or d[i][3] in d[j+1][3]):
G.add_edge(d[i],d[j+1])
The next step on this is to come up with a faster way to iterate through since there will probably only be 1 to 3 edges connecting each node, so 90% of the iteration test will come back false. Suggestions would be welcome!
Since you know that the last character of each list item needs to absolutely match in the same place it's less expensive to check for that first. The code is otherwise doing unnecessary work even though it really doesn't need to. Using timeit you can determine the difference in calculation time by making a few changes, such as checking for the last characters first:
import timeit
d = ['BEBC', 'ABRC']
def test1():
if (d[0][len(d[0])-1] is d[1][len(d[1])-1]):
for i in range(0,2):
if(d[0][i] in d[1][:2]):
return(d[0],d[1])
print(test1())
print(timeit.timeit(stmt=test1, number=1000000))
Result:
('BEBC', 'ABRC')
2.3587113980001959
Original Code:
d = ['BEBC', 'ABRC']
def test2():
for i in range(0,len(d)-1):
for j in range(0,len(d)-1):
if (d[i][0] in d[j+1][:2] or d[i][1] in d[j+1][:2]) and \
(d[i][2] in d[j+1][2] or d[i][3] in d[j+1][3]):
return(d[i],d[j+1])
print(test2())
print(timeit.timeit(stmt=test2, number=1000000))
Result:
('BEBC', 'ABRC')
3.1525327970002763
Now let's take the last list value and change it so that the last character C does not match:
d = ['BEBC', 'ABRX']
New Code:
None
0.766526217000318
Original:
None
2.963771982000253
This is where it's obviously going to pay off in regard to the order of iterating items — especially considering if 90% of the iteration checks could come back false.