I have the below code for a card game, it should remove the N number of cars from the given card list and return a tuple with 2 lists, the first list is the N objects from the original list and the secons list is the remaining cards not extracted from the original list.
lista_cartas = [1,2,3,4,5,6,7,8]
lista_N = []
N = 5
for i in range(N):
extracto = lista_cartas.pop(0)
lista_N.append(extracto)
lista_final = [lista_N, lista_cartas]
print(tuple(lista_final))
([1, 2, 3, 4, 5], [6, 7, 8])
it's working as I want but I need to trasform this into a function that takes the N number and the list as parameters, how can I achieve this?
is this somethinhg valid? or how can I make the function to take a list?
def sacar_cartas(N, lista=[]):
for i in range(N):
extracto = lista_cartas.pop(0)
lista_N.append(extracto)
lista_final = [lista_N, lista_cartas]
print(tuple(lista_final))
You can rework your solution entirely by using list slices:
lista_cartas = [1,2,3,4,5,6,7,8]
def sacar_cartas(todas_cartas, N):
return todas_cartas[:N], todas_cartas[N:]
such that sacar_cartas(lista_cartas, 5) results in the tuple:
([1, 2, 3, 4, 5], [6, 7, 8])
Notice how we can avoid the explicit tuple call by instead returning comma-separated values.
simple conversion:
def sacar_cartas(N, lista):
lista_N = []
for i in range(N):
extracto = lista.pop(0)
lista_N.append(extracto)
return tuple([lista_N, lista])
print(sacar_cartas(5, [1,2,3,4,5,6,7,8]))
Slightly reworked your code so that the function won't alter the passed in list (because of the lista_cartas.copy() call. As to your code and question, Python functions can accept a list as a variable without telling it that it is a list.
lista_cartas = [1,2,3,4,5,6,7,8]
def sacar_cartas(N, lista_cartas):
lista_N = []
lista_ct = lista_cartas.copy()
for i in range(N):
extracto = lista_ct.pop(0)
lista_N.append(extracto)
lista_final = [lista_N, lista_ct]
return lista_final
sacar_cartas(5, lista_cartas)
Python is duck typed. You can pass a list in just like any other variable, without having to define the type:
def function(some_variable):
for element in some_variable:
print(element)
function(['1st element', '2nd element', '3rd element'])
# prints:
# 1st element
# 2nd element
# 3rd element
Doing this:
def function(some_variable=[]):
Does NOT indicate that this variable is a list and is not needed. It instead tells the function that if you do not pass this variable in, it will default to the value []
You don't necessarily have to give a list a default value of empty. You can pass a list to a function by mentioning its variable name:
lista_cartas = [1,2,3,4,5,6,7,8]
lista_N = []
def sacar_cartas(N, lista_cartas, lista_N):
for i in range(N):
extracto = lista_cartas.pop(0)
lista_N.append(extracto)
lista_final = [lista_N, lista_cartas]
print(tuple(lista_final))
# Call the function for it to work
sacar_cartas(N = 5, lista_cartas, lista_N)
You can define variable within the function call if you want. Thats optional because you can define it like a list before the call.
Related
I have a data set which contains keywords,rank_organic and document column. For every keyword there are documents for rank_organic = 1,2,3,4 or 5. But for some keywords I have some rank_organic field missing.
For example: For keyword A, I have rank_organic = 1,2,4,5 and 3 is missing. I want to create a list of documents of length 5 where for rank_organic=3, null or space should come and for rest rank the documents should come.
Below is the code which I am using but it giving error. Please help me how to achieve it.
def key_doc(data):
lis=[]
for i in pd.unique(data['keyword']):
a = data.loc[data['keyword'].isin([i])]
j = i.replace(" ","_")
j = Node(i, parent= Testing,
documents=[(a.loc[(a['rank_organic']==1)])['vocab'].tolist()[0]
,(a.loc[(a['rank_organic']==2)])['vocab'].tolist()[0]
,(a.loc[(a['rank_organic']==3)])['vocab'].tolist()[0]
,(a.loc[(a['rank_organic']==4)])['vocab'].tolist()[0]
,(a.loc[(a['rank_organic']==5)])['vocab'].tolist()[0]])
# print j.name, len(j.documents)
lis.append(j)
return lis
ERROR:
,(a.loc[(a['rank_organic']==3)])['vocab'].tolist()[0]
IndexError: list index out of range
I recommend you use a list or dictionary comprehension for this and use next to retrieve the first element. next also has an optional argument, which we define as [] (empty list), if there are no elements to extract.
docs = [next(iter(a.loc[a['rank_organic'] == i, 'vocab'].tolist()), []) \
for i in range(1, 6)]
Then feed docs as your class instance argument.
Below is a minimal example of how the next(iter(lst), ...) method works:-
lst = [[1, 2, 3], [4], [], [3, 5]]
res = [next(iter(i), []) for i in lst]
# [1, 4, [], 3]
I want to rotate k element in a list in python. For example, n = 7, k = 3, and the array [1,2,3,4,5,6,7] is rotated to [5,6,7,1,2,3,4].
Here is the statement I wrote. It seems to work in the command line.
nums = nums[k%len(nums):] + nums[:k%len(nums)]
But when I encapsulate it in a function like:
def rotate(nums, k):
nums = nums[k%len(nums):] + nums[:k%len(nums)]
return
I want to modify nums directly, but this function doesn't work.
I know that I can use a for loop like:
for i in range(k):
nums.insert(0,nums.pop())
but I want to know why the previous method doesn't work?
What you want is a slice assignment:
nums[:] = nums[k%len(nums):] + nums[:k%len(nums)]
This mutates the list that was passed in, so the change is visible after the function returns. Assigning just to nums merely makes nums point to a different list inside the function; it doesn't affect the original list.
Are you sure you want to modify nums? You need not create a separate list even if you do not modify nums. One advantage of the following approach is that it will work with any sequence.
from itertools import islice
def rotate(lst, k):
n = len(lst)
start = n - (k % n) #handle all ints
for item in islice(lst, start, None):
yield item
for item in islice(lst, 0, start):
yield item
If you insist on modifying nums as you say, you can still do so. E.g.,
nums = [x + 1 for x in range(7)]
nums[:] = rotate(nums,-10)
The nums that is inside the function is only within that function. So you need to return it from that function. One way is like this (python 2.7 code, add parentheses to print if you use 3.x):
nums = [1, 2, 3, 4, 5, 6, 7]
k = 3
def rotate(nums, k):
return nums[k%len(nums):] + nums[:k%len(nums)]
print 'Original', nums
nums = rotate(nums, k)
print 'Rotated', nums
Why does this function result in:
Oops, try again. remove_duplicates([]) resulted in an error: list index out of range"?
my function is as follows
def remove_duplicates(listIn):
listSorted = sorted(listIn)
prevInt = listSorted[0]
listOut = []
listOut.append(prevInt)
for x in listSorted:
if (x != prevInt):
prevInt = x
listOut.append(x)
print listOut
return listOut
remove_duplicates([1,2,3,3,3])
which outputs:
[1, 2, 3]
None
Thank you.
to answer your question you need to just check for the length of your list and return if its empty
if not listIn:
return []
however your whole approach could be simplified with a set like so
def remove_duplicates(listIn):
return list(set(listIn))
output:
>>> print remove_duplicates([1,2,3,3,3])
>>> [1, 2, 3]
of course this is assuming you want to keep your data in a list.. if you dont care then remove the outer list() conversion to make it faster. regardless this will be a much faster approach than what you have written
I am a student in an intro-level python class, and my task is to define "reverse(mylist)" using while loop
This is what I have so far:
def reverse(mylist):
a=0
b=len(mylist)
xlist=mylist
while(a!=b):
mylist[a]=xlist[(-a)-1]
a+=1
return mylist
Let's say the input list is [1,2,3,4,5,6], and using my reverse function I will get the output [6, 5, 4, 4, 5, 6]... And [1,2,3,4,5] will become [5,4,3,4,5]
I am not sure what I am doing wrong here.
Following statement makes both xlist, mylist reference same list object:
xlist = mylist
You need to copy it.
xlist = mylist[:]
BTW, using for loop, you don't need to increment a manually:
for a in range(len(mylist)):
....
def reverse(mylist):
a=0
b=len(mylist)
xlist=[]
while(a!=b):
mylist[a:a]=xlist[(-a)-1]
a+=1
return mylist
list is transfered by referance not by value.
you need to create new list.
"xlist = mylist" only create a referance.
ps
"for in" is more commonly used in python.
for i in range(2, -1, -1):
xlist.append(mylist[i])
or:
xlist = [mylist[i], for i in range(2, -1, -1) ]
i have a list of dictionaries. there are several points inside the list, some are multiple. When there is a multiple entry i want to calculate the average of the x and the y of this point. My problem is, that i don't know how to loop through the list of dictionaries to compare the ids of the points!
when i use something like that:
for i in list:
for j in list:
if i['id'] == j['id']:
point = getPoint(i['geom'])
....
sorry, the formating is a little bit tricky... the second loop is inside the first one...
i think it compares the first entry of the list, so it's the same... so i have to start in the second loop with the second entry, but i can't do that with i-1 because i is the hole dictionary...
Someone an idea?
thanks in advance!
for j in range(1, len(NEWPoint)):
if i['gid']==j['gid']:
allsamePoints.append(j)
for k in allsamePoints:
for l in range(1, len(allsamePoints)):
if k['gid']==l['gid']:
Point1 = k['geom']
Point2=l['geom']
X=(Point1.x()+Point2.x())/2
Y=(Point1.y()+Point2.y())/2
AVPoint = QgsPoint(X, Y)
NEWReturnList.append({'gid': j['gid'], 'geom': AVPoint})
del l
for m in NEWReturnList:
for n in range(1, len(NEWReturnList)):
if m['gid']==n['gid']:
Point1 = m['geom']
Point2=n['geom']
X=(Point1.x()+Point2.x())/2
Y=(Point1.y()+Point2.y())/2
AVPoint = QgsPoint(X, Y)
NEWReturnList.append({'gid': j['gid'], 'geom': AVPoint})
del n
else:
pass
ok, i think... at the moment thats more confusing :)...
One way would be changing the way you store your points, because as you already noticed, it's hard to get what you want out of it.
A much more useful structure would be a dict where the id maps to a list of points:
from collections import defaultdict
points_dict = defaultdict(list)
# make the new dict
for point in point_list:
id = point["id"]
points_dict[id].append(point['geom'])
def avg( lst ):
""" average of a `lst` """
return 1.0 * sum(lst)/len(lst)
# now its simple to get the average
for id in points_dict:
print id, avg( points_dict[id] )
I'm not totally sure what you want to do, but I think list filtering would help you. There's built-in function filter, which iterates over a sequence and for each item it calls user-defined function to determine whether to include that item in the resulting list or not.
For instance:
def is4(number):
return number == 4
l = [1, 2, 3, 4, 5, 6, 4, 7, 8, 4, 4]
filter(is4, l) # returns [4, 4, 4, 4]
So, having a list of dictionaries, to filter out all dictionaries with certain entry equal to a given value, you could do something like this:
def filter_dicts(dicts, entry, value):
def filter_function(d):
if entry not in d:
return False
return d[entry] == value
return filter(filter_function, dicts)
With this function, to get all dictionaries with the "id" entry equal to 2, you can do:
result = filter_dicts(your_list, "id", 2)
With this, your main loop could look something like this:
processed_ids = set()
for item in list:
id = item['id']
if id in processed_ids:
continue
processed_ids.add(id)
same_ids = filter_dicts(list, "id", id)
# now do something with same_ids
I hope I understood you correctly and that this is helpful to you.