How to create a list from another list according to a function
Question:
I would like to create a list which has values which correspond to another list.
For example if I had:
listA = [1, 2, 3, 4, 5,...]
and I would like to create another list which is the same, except all the values were varied according to x^2 (or any other function), giving:
listB = [1, 4, 9, 16,25, ...]
I have already tried to do this by doing a while loop:
listA = [1, 2, 3, 4]
listB = range(1, 4, 1)
i = 0
while i <= 4:
listB [i] = (listA [i]) ** 2
i = i + 1
print listA
print listB
But it just spits out an error message:
Traceback (most recent call last):
File "/home/tim/Desktop/Python/test.py", line 5, in <module>
listB [i] = (listA [i]) ** 2
IndexError: list assignment index out of range
Answers:
You can try this, using a lambda function to apply whatever change you want to each element in the list. In this case, the function is squaring every value in the list:
listA = [1, 2, 3, 4, 5,...]
operation = lambda x:x**2
new_list = map(operation, listA)
Also, you can perform the function operation in list comprehension:
new_list = [i**2 for i in listA]
There is a smart syntax for building lists out of others:
listB = [x*x for x in listA]
Edit: Never use range
as a list directly, even if it makes a list in Python 2, because it spits out a range
object in Python 3. Use list(range(...))
instead!
The popular numpy library provides a more concise syntax for doing such list operations, when the list would only consist out of numbers. It uses arrays that are faster in some circumstances like the element wise multiplication. The statement above can be rewritten as:
arrayB = arrayA * arrayA
or
arrayB = arrayA ** 2
or (not always recommended)
f = lambda a: a**2
arrayB = f(arrayA)
The element wise multiplication is sometimes referred to as the hadamard product, that comes from vector arithmetics (there is also a@b
in numpy). In numpy you have to create the arrays with np.array
or np.arange
. The last is similar to range
in Python 2 in the way, that it creates an array directly.
You can use the numpy
library with a function called power
import numpy as np
listA = [1,2,3,4]
new_li = np.power(listA, 2)
print new_li
>>> [ 1 4 9 16]
There are multiple ways of doing what you are asking, others have pointed out list
comprehensions and map
s.
Reviewing your code:
listB = range(1, 4, 1)
The is only 3 items, [1, 2, 3]
, range()
is up to but not including the stop
arg. You don’t need to initialise your listB
because you can just listB.append()
in the loop, so listB = []
is sufficient. Note in python3 this assigns a range()
object to listB
and it doesn’t initialise the list as you intended.
i = 0
while i <= 4:
This loops 5 times, i = 0, 1, 2, 3, 4
, and because this is more than listB
(and listA)
it results in the IndexError
you are seeing. The normal way to do fixed loops would be with a for
loop, e.g. for i in range(4):
. However, you can loop directly over the elements in listA
with for i in listA:
and this would be considerd more pythonic
listB [i] = (listA [i]) ** 2
This doesn’t work because your loop goes to from 0
to 4
(inclusive) and range(1, 4, 1)
is only 3 items [1, 2, 3]
.
i = i + 1
Unnecessary with a for loop
.
Putting it all together and doing it iteratively as you’ve described you would do:
listA = [1, 2, 3, 4]
listB = []
for i in listA:
listB.append(i**2)
print(listA) # [1, 2, 3, 4]
print(listB) # [1, 4, 9, 16]
Note: My preference would be for the list comprehension:
listB = [i**2 for i in listA]
Python provides the enumerate
function when you need to iterate over a list and need the index. That way you avoid easy-to-avoid IndexError
s like these:
listA = [1, 2, 3, 4]
listB = [None]*4
for idx, item in enumerate(listA):
listB[idx] = item ** 2
But in most cases you don’t even need to create listB
beforehand, you could let Python create it for you with map
or a “list comprehension”. The other answers already covered that but I wanted to share some way of using map
without lambda
:
import itertools
listB = list(map(pow, listA, itertools.repeat(2, len(listA))))
You can omit the outer list()
if you’re using python 2.x.
You can use a list comprehension:
listA = [1, 2, 3, 4]
listB = [x**2 for x in listA]
Or a normal loop:
listA = [1, 2, 3, 4]
listB = []
for x in listA:
listB.append(x**2)
I would like to create a list which has values which correspond to another list.
For example if I had:
listA = [1, 2, 3, 4, 5,...]
and I would like to create another list which is the same, except all the values were varied according to x^2 (or any other function), giving:
listB = [1, 4, 9, 16,25, ...]
I have already tried to do this by doing a while loop:
listA = [1, 2, 3, 4]
listB = range(1, 4, 1)
i = 0
while i <= 4:
listB [i] = (listA [i]) ** 2
i = i + 1
print listA
print listB
But it just spits out an error message:
Traceback (most recent call last):
File "/home/tim/Desktop/Python/test.py", line 5, in <module>
listB [i] = (listA [i]) ** 2
IndexError: list assignment index out of range
You can try this, using a lambda function to apply whatever change you want to each element in the list. In this case, the function is squaring every value in the list:
listA = [1, 2, 3, 4, 5,...]
operation = lambda x:x**2
new_list = map(operation, listA)
Also, you can perform the function operation in list comprehension:
new_list = [i**2 for i in listA]
There is a smart syntax for building lists out of others:
listB = [x*x for x in listA]
Edit: Never use range
as a list directly, even if it makes a list in Python 2, because it spits out a range
object in Python 3. Use list(range(...))
instead!
The popular numpy library provides a more concise syntax for doing such list operations, when the list would only consist out of numbers. It uses arrays that are faster in some circumstances like the element wise multiplication. The statement above can be rewritten as:
arrayB = arrayA * arrayA
or
arrayB = arrayA ** 2
or (not always recommended)
f = lambda a: a**2
arrayB = f(arrayA)
The element wise multiplication is sometimes referred to as the hadamard product, that comes from vector arithmetics (there is also a@b
in numpy). In numpy you have to create the arrays with np.array
or np.arange
. The last is similar to range
in Python 2 in the way, that it creates an array directly.
You can use the numpy
library with a function called power
import numpy as np
listA = [1,2,3,4]
new_li = np.power(listA, 2)
print new_li
>>> [ 1 4 9 16]
There are multiple ways of doing what you are asking, others have pointed out list
comprehensions and map
s.
Reviewing your code:
listB = range(1, 4, 1)
The is only 3 items, [1, 2, 3]
, range()
is up to but not including the stop
arg. You don’t need to initialise your listB
because you can just listB.append()
in the loop, so listB = []
is sufficient. Note in python3 this assigns a range()
object to listB
and it doesn’t initialise the list as you intended.
i = 0
while i <= 4:
This loops 5 times, i = 0, 1, 2, 3, 4
, and because this is more than listB
(and listA)
it results in the IndexError
you are seeing. The normal way to do fixed loops would be with a for
loop, e.g. for i in range(4):
. However, you can loop directly over the elements in listA
with for i in listA:
and this would be considerd more pythonic
listB [i] = (listA [i]) ** 2
This doesn’t work because your loop goes to from 0
to 4
(inclusive) and range(1, 4, 1)
is only 3 items [1, 2, 3]
.
i = i + 1
Unnecessary with a for loop
.
Putting it all together and doing it iteratively as you’ve described you would do:
listA = [1, 2, 3, 4]
listB = []
for i in listA:
listB.append(i**2)
print(listA) # [1, 2, 3, 4]
print(listB) # [1, 4, 9, 16]
Note: My preference would be for the list comprehension:
listB = [i**2 for i in listA]
Python provides the enumerate
function when you need to iterate over a list and need the index. That way you avoid easy-to-avoid IndexError
s like these:
listA = [1, 2, 3, 4]
listB = [None]*4
for idx, item in enumerate(listA):
listB[idx] = item ** 2
But in most cases you don’t even need to create listB
beforehand, you could let Python create it for you with map
or a “list comprehension”. The other answers already covered that but I wanted to share some way of using map
without lambda
:
import itertools
listB = list(map(pow, listA, itertools.repeat(2, len(listA))))
You can omit the outer list()
if you’re using python 2.x.
You can use a list comprehension:
listA = [1, 2, 3, 4]
listB = [x**2 for x in listA]
Or a normal loop:
listA = [1, 2, 3, 4]
listB = []
for x in listA:
listB.append(x**2)