What are some Alternatives to enumerate function in Python? - python

I have a question I need to solve using python, using a def function. Basically take a list of numbers, and then and add a letter at the end of each element in the list.
I was finally able to do it, but for various reasons I need to find an alternative way that does not use enumerate. Is there any way to make this work without using enumerate function, something simpler. Here is my working code:
def addletter( mylist ):
for index, item in enumerate(mylist):
mylist[index] = str(item)
for i in range(len(mylist)):
mylist[i] = mylist[i] + randomletter
return
# Now you can call addletter function
mylist = [1,2,3,4,5,6,7,8,9,];
randomletter= 'a'
addletter( mylist );
print (mylist)

Done without the enumerate function:
(you can remove the other loop, and you don't have to call return, python will automatically return None):
def add_letter(mylist):
for i in range(len(mylist)):
mylist[i] = str(mylist[i]) + randomletter
# Now you can call addletter function
mylist = [1, 2, 3, 4, 5, 6, 7, 8, 9, ];
randomletter = 'a'
add_letter(mylist)
print(mylist)

Related

Function that takes an Int and a List

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.

Python - Iterating and Replacing List Index via enumerate()

I have a python script that imports a CSV file and based on the file imported, I have a list of the indexes of the file.
I am trying to match the indexes in FILESTRUCT to the CSV file and then replace the data in the column with new generated data. Here is a code snip-it:
This is just a parsed CSV file returned from my fileParser method:
PARSED = fileParser()
This is a list of CSV column positions:
FILESTRUCT = [6,7,8,9,47]
This is the script that is in question:
def deID(PARSED, FILESTRUCT):
for item in PARSED:
for idx, lis in enumerate(item):
if idx == FILESTRUCT[0]:
lis = dataGen.firstName()
elif idx == FILESTRUCT[1]:
lis = dataGen.lastName()
elif idx == FILESTRUCT[2]:
lis = dataGen.email()
elif idx == FILESTRUCT[3]:
lis = dataGen.empid()
elif idx == FILESTRUCT[4]:
lis = dataGen.ssnGen()
else:
continue
return(PARSED)
I have verified that it is correctly matching the indices (idx) with the integers in FILESTRUCT by adding a print statement at the end of each if statement. That works perfectly.
The problem is that when I return(PARSED) it is not returning it with the new generated values, it is instead, returning the original PARSED input values. I assume that I am probably messing something up with how I use the enumerate method in my second loop, but I do not understand the enumerate method well enough to really know what I am messing up here.
You can use
item[idx] = dataGen.firstName()
to modify the underlying item. The reason here is that enumerate() returns (id, value) tuples rather than references to the iterable that you passed.
Given your example above you may not even need enumerate, because you're not parsing the lis at all. So you could also just do
for i in range(len(item)):
# your if .. elif statements go here ...
item[i] = dataGen.firstName()
On a side-note, the elif statements in your code will become unwieldy once you start adding more conditions and columns. Maybe consider making FILESTRUCT a dictionary like:
FILESTRUCT = {
6: dataGen.firstName,
7: dataGen.lastName,
....
}
...
for idx in range(len(item)):
if idx in FILESTRUCT.keys():
item[idx] = FILESTRUCT[idx]()
So PARSED is an iterable, and item is an element of it and is also an iterable, and you want to make changes to PARSED by changing elements of item.
So let's do a test.
a = [1, 2, 3]
print 'Before:'
print a
for i, e in enumerate(a):
e += 10
print 'After:'
print a
for e in a:
e += 10
print 'Again:'
print a
a[0] += 10
print 'Finally:'
print a
The results are:
Before:
[1, 2, 3]
After:
[1, 2, 3]
Again:
[1, 2, 3]
Finally:
[11, 2, 3]
And we see, a is not changed by changing the enumerated elements.
You aren't returning a changed variable. You don't ever change the variable FILESTRUCT. Rather make another variable, make it as you loop through FILESTRUCT and then return your new FILE.
You can't change the values in a loop like that, Kind of like expecting this to return all x's:
demo_data = "A string with some words"
for letter in demo_data:
letter = "x"
return demo_data
It won't, it will return: "A string with some words"

Modify a int list in function in python

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

Apply function to some values in list

I have a function that takes a list of tasks, create threads and solves a complex task for each task.
To simplify lets just say it is this function:
def efficient_function_that_only_takes_a_list(list):
return [-x for x in list]
Now, all I need to do is to have a list and give it to the function:
efficient_function_that_only_takes_a_list(my_list)
My problem now is that I have realized that not all of the items in the list needs to be processed by the function. But I want to keep the order and only process some of them. This is what I came up with.
Anyone have a more pythonic way?
my_list = [3,2,3,4,5,6,7,8,9]
def my_condition(x):
return x%2 == 0
def efficient_function_that_only_takes_a_list(list):
return [-x for x in list]
#What I want: [1,-2,3,-4,5,-6,7,-8,9]
# My attempt:
def apply_to_some(mylist, condition, function):
valid = [(i,x) for i,x in enumerate(mylist) if condition(x)]
index, values = zip(*valid)
results = function(values)
for new_value, ix in zip(results,index):
mylist[ix] = new_value
return my_list
print apply_to_some(my_list, my_condition, efficient_function_that_only_takes_a_list) #=> [3, -2, 3, -4, 5, -6, 7, -8, 9]
Edit: I really need my function to take a list and not a single item as I need to make it run efficiently i parallel like in this article: https://medium.com/p/40e9b2b36148
It would be neater to do something like:
def apply_to_some(mylist, condition, function):
return [function(x) if condition(x) else x for x in mylist]
Although note that this form doesn't mutate mylist.
However, if your efficient function relies on a list, aside from a few tweaks that just reduce the line count, there's not much to improve on what you have.
Or if list comprehensions make your head spin, use map:
def apply_to_some(mylist, condition, function):
return map(lambda x: function(x) if condition(x) else x, mylist)

Creating a reverse order list using while loop - unexpected results

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) ]

Categories