I am making a hangman game and I want to be able to replace the list of original words with a list of new words typed in by the user. At the minute my code is this:
gamewords[:] = newgamewords[:]
But this does not seem to work...
The original list is this:
gamewords= ['blue','violet','red','orange','fuchsia','cyan','magenta','azure','black','turquoise','pink','scarlet']
A word is then chosen for the list randomly
word=gamewords[random.randint(0,len(gamewords)-1)]
i want to change it so that the word is chosen from the new list, how do i do this?
You probably meant to do this:
gamewords = newgamewords[:] # i.e. copy newgamewords
Another alternative would be
gamewords = list(newgamewords)
I find the latter more readable.
Note that when you 'copy' a list like both of these approaches do, changes to the new copied list will not effect the original. If you simply assigned newgamewords to gamewords (i.e. gamewords = newgamewords), then changes to gamewords would effect newgamewords.
Relevant Documentation
list
I'm not sure what you exactly want. There are two options:
gamewords = newgamewords[:]
gamewords = newgamewords
The difference is that the first option copies the elements of newgamewords and assigns it to gamewords. The second option just assigns a reference of newgamewords to gamewords. Using the second version, you would change the original newgamewords-list if you changed gamewords.
Because you didn't give more of your source code I can't decide which will work properly for you, you have to figure it out yourself.
The obvious choice of functions to use to select one, or a set number of items randomly from a larger list would be random.choice() or random.choices().
>>> gamewords= ['blue','violet','red','orange','fuchsia','cyan','magenta','azure','black','turquoise','pink','scarlet']
>>> random.choice(gamewords)
'turquoise'
>>> random.choice(gamewords)
'orange'
>>> random.choice(gamewords)
'cyan'
>>> random.choices(gamewords, k=3)
['fuchsia', 'orange', 'red']
>>> random.choices(gamewords, k=2)
['turquoise', 'black']
>>>
Not sure if you were able to find the answer to this but I had a similar issue and I resolved it using this method:
for x, y in zip(original_col, np.arange(0, len(original_col), 1)):
df['Term Ldesc'] = df['Term Ldesc'].replace(x, y)
Hope this helps!
Related
>>> a = bpy.context.selected_objects
>>> a[:2]
[bpy.data.objects['Sphere.001'], bpy.data.objects['Sphere.010']]
>>>
Two list results.
what i need is
It is to move the number after Sphere to notepad.
I do not know.
001 and 010
thank you.
Is this what you want?
for a in bpy.context.selected_objects:
print(a.name.split(".")[-1])
In Blender, you can just split the object's name on the '.' and take the last element in the resulting list. That should print out all those numbers that you want to copy.
#Matti is probably giving you good information on Blender, and the loop will work, but the most direct route to the general case of getting a modified version of each item in a list is by using a list comprehension.
x = ["Sphere.001", "Sphere.010"]
print([y.split(".")[-1] for y in x])
My function takes a number, and a list of numbers.
If 2 numbers in the list add up to the original number, in the form [Num1, Num2].
Now I don't want any "duplicates" i.e. I only want [4, -7] returned and not [4, -7], [-7, 4].
def pairs(n, num_list):
newest_list = []
for j in range(len(num_list)):
for i in range(len(num_list)-1):
if num_list[j] + num_list[i+1] == n:
newest_list.append([num_list[j], num_list[i+1]])
return newest_list
Now I'd like a hint rather than code posted, a simple.
My question is:
Do I have the ability to do that within my code, and if so, a hint would be great, or will I need to define another function to do that for me?
You definitely have the ability to do that within your code.
A hint to complete this would be to think about at what point in your code it makes sense to stop searching for further matches and to return what you've found. Let me know if that's too cryptic!
You can still do that in your current code by simply appending these two numbers into a Set. For more info, this will help you.
if you have 2 lists l1, and l2 where:
l1=[1,2]
l2=[2,1]
If you convert them to sets, you can compare them and they will evaluate to True if they have the same elements, no matter what the order is:
set(l1) == set(l2) # this evaluates to True
In your if condition, before appending the numbers, you can check if the set set([num_list[j], num_list[i+1]]) is already in newest_list.
I am tempted to write some code, but you said not to, so I'll leave it here :p
You can leave your code the way it is, but before you return the list, you can filter the list with a predicate that the pair [a,b] is only accepted if pair [b,a] is not in the list
When adding a pair [a, b] to the result list, sort the pair, then see if it's in the result list. If so, don't add it.
Also, consider using a Python set.
This problem is very simple to appreciate, here is the program -
hisc = [1,2,3,4]
print("\n", hisc)
ohisc = hisc
hisc.append(5)
print("\nPreviously...", ohisc)
print("\nAnd now...", hisc)
input("\nETE")
When I run it ohisc gets the 5. Why does ohisc change? How can I stop it from changing?
Apologies if this is something obvious.
Python variables are references. As such, the assignment copies the reference rather than the content of the variable.
In order to avoid this, all you have to do is create a new object:
ohisc = list(hisc)
This is using the list constructor which creates a new list from a given iterable.
Alternatively you can also assign from a slice (which creates a new object):
ohisc = hisc[:]
[] is the general slice operator which is used to extract a subset from a given collection. We simply leave out the start and end position (they default to the begin and end of the collection, respectively).
You definitely need to understand everything in Konrad Rudolph's answer. And I think in your specific case, that's what you want, too. But often there's a better way: If you avoid mutating objects (that is, changing them in-place), it never matters whether two names are referring to the same object or not. For example, you can change this:
hisc.append(5)
to this:
hisc = hisc + [5]
That doesn't change hisc in-place; it creates a new list, with the 5 added on to the end of it, and then assigns that to hisc. So, the fact that ohisc was pointing to the same list as hisc doesn't matter—that list is still there, unchanged, for ohisc to point to.
Let's say you wanted to replace all the negative values of the list with 0. That's pretty easy with mutation:
for i in range(len(lst)):
list[i] = max(list[i], 0)
But even easier without:
lst = [max(elem, 0) for elem in lst]
Now, what if you wanted to remove every negative list element? You can't change the shape of a sequence while looping over it, so you have to either make a copy of the list (so you can loop over one copy while you change the other), or come up with a more complicated algorithm (e.g., swap each 0 backward and then remove all the 0's at the end). But it's easy to do immutably:
lst = [elem for elem in lst if elem >= 0]
So, when would you ever want to mutate? Well, often you want two references to the same object, so when you update one, the other one sees the changes. In that case, you obviously have to have actual changes for the other one to see.
Here's a good explanation of what is happening: Python: copying a list the right way
Basically, you're making a pointer to the list but what you want to do is make a copy of the list.
Try this instead:
hisc = [1,2,3,4]
ohisc = hisc[:]
This is the only way i can think of looks like this:
var = 1
list = [2, 3, 4]
newList = [var,] + list
Is it the right way?
Update: I need to make a new list so insert would not help
Your method is fine (other than the extra comma not needed for a 1-list); people have done it this way for a long time.
In general you want to avoid adding things to the start of a list in Python: it's O(n) in cost.
If you have to (and often the inefficiency doesn't matter), you can do this:
[a] + other_list
If you don't mind updating the list you have, you can do this:
other_list.insert(0, a)
If you can use an iterator rather than a list, you can efficiently use:
itertools.chain([a], other_list)
I am not sure what you want to imply by using the , after var but generally you won;t need it. As you were trying to get other options here is another way to do
lst.insert(0,var)
If you are not intending to modify the original list you may want to copy it to another list
newList=lst[::]
and then do the insert
lst.insert(0,var)
It's a matter of style but I prefer
newList=[var]+lst
Note**
Generally if you are not intending to modify the original list,
newlst = [var] + lst
looks cleaner
but in case you want to modify in place your options are
lst = [var] + lst
or
lst.insert(0,var)
The later one is preferable because it is more readable and moreover you can use it inside lambda and list-comprehension :-)
Use the append method:
list.append(var)
or insert of you want to place the new element in the beginning:
list.insert(0,var)
What about this?
a_list = []
v = 1
list_to_add = [2, 3, 4]
a_list.append(v)
a_list.extend(list_to_add)
For your reference, go through this LIST
Let's say I have a function f() that takes a list and returns a mutation of that list. If I want to apply that function to five member variables in my class instance (i), I can do this:
for x in [i.a, i.b, i.c, i.d, i.e]:
x[:] = f(x)
1) Is there a more elegant way? I don't want f() to modify the passed list.
2) If my variables hold a simple integer (which won't work with the slice notation), is there also a way? (f() would also take & return an integer in this case)
Another solution, though it's probably not elegant:
for x in ['a', 'b', 'c', 'd', 'e']:
setattr(i, x, f(getattr(i, x)))
Python doesn't have pass by reference. The best you can do is write a function which constructs a new list and assign the result of the function to the original list. Example:
def double_list(x):
return [item * 2 for item in x]
nums = [1, 2, 3, 4]
nums = double_list(nums) # now [2, 4, 6, 8]
Or better yet:
nums = map(lambda x: x * 2, nums)
Super simple example, but you get the idea. If you want to change a list from a function you'll have to return the altered list and assign that to the original.
You might be able to hack up a solution, but it's best just to do it the normal way.
EDIT
It occurs to me that I don't actually know what you're trying to do, specifically. Perhaps if you were to clarify your specific task we could come up with a solution that Python will permit?
Ultimately, what you want to do is incompatible with the way that Python is structured. You have the most elegant way to do it already in the case that your variables are lists but this is not possible with numbers.
This is because variables do not exist in Python. References do. So i.x is not a list, it is a reference to a list. Likewise, if it references a number. So if i.x references y, then i.x = z doesn't actually change the value y, it changes the location in memory that i.x points to.
Most of the time, variables are viewed as boxes that hold a value. The name is on the box. In python, values are fundamental and "variables" are just tags that get hung on a particular value. It's very nice once you get used to it.
In the case of a list, you can use use slice assignment, as you are already doing. This will allow all references to the list to see the changes because you are changing the list object itself. In the case of a number, there is no way to do that because numbers are immutable objects in Python. This makes sense. Five is five and there's not much that you can do to change it. If you know or can determine the name of the attribute, then you can use setattr to modify it but this will not change other references that might already exist.
As Rafe Kettler says, if you can be more specific about what you actually want to do, then we can come up with a simple elegant way to do it.