Python functions parameter - python

why append method works on original numbers list and it changed numbers list but I can't reassign numbers list to [4,5,6]?
def change(numbers_list):
numbers_list.append(4)
numbers_list = [4,5,6]
numbers = [1,2,3]
change(numbers)
print(numbers)
when code runs this printed:
[1,2,3,4]
why not [4,5,6]?

The function of append is to add an item to an existing list. The reason for no effect is that you are doing many invalid things. For one you are calling the function but never assigning the return to a variable. Second your use of append is void because directly after you declare numbers_list = [4, 5, 6]. If you goal of the function is just to change [1, 2, 3] to [4, 5, 6] the setup would be this.
def change(numbers_list):
numbers_list = [4,5,6]
return numbers_list
numbers = [1,2,3]
numbers = change(numbers)
print(numbers)
# [4, 5, 6]
Although this would suffice
numbers = [1, 2, 3]
numbers = [4, 5, 6]
print(numbers)
# [4, 5, 6]

Related

How to append values to list?

I want to append my list with values for each loop iteration:
for i in range (4,10):
a_list = [1,2,3]
a_list = a_list.append(i)
The wanted output would be [1,2,3,4,5,6,7,8,9]. But I get None. Also printing type(a_list) after using .append() gives me <class'NoneType'>. What is the problem here ?
firstly, you have to mention a_list before for. instead, you will get [1, 2, 3, 9]. secondly, you give the a_list a value of a_list.append() function.
a_list = [1, 2, 3]
for i in range(4, 10):
a_list.append(i)
it is mainly because of the fact that list.append method does not return anything, it appends the given value to the list in-place.
we can confirm this by the simple example below
a = list()
b = a.append(5)
>> print(b)
None
>> print(a)
[5]
As matter of fact,there is a simpler and more performant way to achieve this
>> a_list = [1,2,3]
>> a_list += list(range(4, 10))
>> print(a_list)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Here, we first shape a new list from a iterator range(4, 10),
then we concate the two list together to get the list we want by adding the new list to the original list a_list.
by doing this, we can avoid the overhead caused by repeatedly call the list.append method in a for loop
a_list = []
for i in range (1,10):
a_list.append(i)
print(a_list)
Output
[1, 2, 3, 4, 5, 6, 7, 8, 9]
You have the wrong indentation on the loop.You need to add i at each iteration. Also, to get the list you want, you need to add 1, then 2, then 3, and so on. i this is what needs to be added. Put print(i) and print each iteration.
a_list = [1,2,3]
for i in range (4,10):
a_list.append(i)
print(a_list)
If you use your option, it will be correct to declare an array once. And then only add values. See below.
[1, 2, 3, 4, 5, 6, 7, 8, 9]

How to add the first four digits in to another list

I want to take the first four digits from the already shuffled list and add them to a new list. I thought of append but all it does is return the whole list 4 times.
base = [1, 2, 3, 4, 5, 6]
random.shuffle(base)
correct = []
for i in range(4):
correct.append(base)
print(correct)
You can do it like this:
import random
base = [1, 2, 3, 4, 5, 6]
random.shuffle(base)
correct = base[:4]
print(correct)
This works because of list slicing
If for whatever reason you want to avoid using list slicing here is how you would do it in a way you originally tried.
base = [1, 2, 3, 4, 5, 6]
random.shuffle(base)
correct = []
for i in range(4):
correct.append(base[i])
print(correct)

function that concatenates two lists python Codecademy

I am stucked at ex 18,chapter lists and function from CODECADEMY.
"Create a function called flatten that takes a single list and concatenates all the sublists that are part of it into a single list."
"1 On line 3, define a function called flatten with one argument called lists.
2 Make a new, empty list called results.
3 Iterate through lists. Call the looping variable numbers.
4 Iterate through numbers.
5 For each number, .append() it to results.
6 Finally, return results from your function."
Here is my code:
And the error:
Oops, try again. flatten([[1, 2], [3, 4]]) returned [1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4] instead of [1, 2, 3, 4]
n = [[1, 2, 3], [4, 5, 6, 7, 8, 9]]
# Add your function here
results=[]
def flatten(lists):
for numbers in lists:
for number in numbers:
results.append(number)
return results
print flatten(n)
I can't figure out what is wrong.
Your mistake is that you declared the results list globally, while you should have declared it in the scope of your function.
Because results is outside of the function, it doesn't reset when you run flatten() the second time. Instead, the newly flattened array is added on top of the one from the previous run.
You should move results inside your function like so:
def flatten(lists):
results[]
for numbers in lists:
for number in numbers:
results.append(number)
return results
That way it resets every time you run the function and thus returns the correct result.
Convert this:
results=[]
def flatten(lists):
to this:
def flatten(lists):
results=[]
Is you data input wrong?
If you replace you first line of code
n = [[1, 2, 3], [4, 5, 6, 7, 8, 9]]
with
n = [[1, 2], [3, 4]].
The output will be
[1, 2, 3, 4]
Also, you should place results=[] inside function def flatten(lists):
def flatten(lists):
results=[]
for numbers in lists:
for number in numbers:
results.append(number)
return results

Separating same numbers from the list and making the list of such lists [duplicate]

From this list:
N = [1,2,2,3,3,3,4,4,4,4,5,5,5,5,5]
I'm trying to create:
L = [[1],[2,2],[3,3,3],[4,4,4,4],[5,5,5,5,5]]
Any value which is found to be the same is grouped into it's own sublist.
Here is my attempt so far, I'm thinking I should use a while loop?
global n
n = [1,2,2,3,3,3,4,4,4,4,5,5,5,5,5] #Sorted list
l = [] #Empty list to append values to
def compare(val):
""" This function receives index values
from the n list (n[0] etc) """
global valin
valin = val
global count
count = 0
for i in xrange(len(n)):
if valin == n[count]: # If the input value i.e. n[x] == n[iteration]
temp = valin, n[count]
l.append(temp) #append the values to a new list
count +=1
else:
count +=1
for x in xrange (len(n)):
compare(n[x]) #pass the n[x] to compare function
Use itertools.groupby:
from itertools import groupby
N = [1,2,2,3,3,3,4,4,4,4,5,5,5,5,5]
print([list(j) for i, j in groupby(N)])
Output:
[[1], [2, 2], [3, 3, 3], [4, 4, 4, 4], [5, 5, 5, 5, 5]]
Side note: Prevent from using global variable when you don't need to.
Someone mentions for N=[1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 1] it will get [[1], [2, 2], [3, 3, 3], [4, 4, 4, 4], [5, 5, 5, 5, 5], [1]]
In other words, when numbers of the list isn't in order or it is a mess list, it's not available.
So I have better answer to solve this problem.
from collections import Counter
N = [1,2,2,3,3,3,4,4,4,4,5,5,5,5,5]
C = Counter(N)
print [ [k,]*v for k,v in C.items()]
You can use itertools.groupby along with a list comprehension
>>> l = [1,2,2,3,3,3,4,4,4,4,5,5,5,5,5]
>>> [list(v) for k,v in itertools.groupby(l)]
[[1], [2, 2], [3, 3, 3], [4, 4, 4, 4], [5, 5, 5, 5, 5]]
This can be assigned to the variable L as in
L = [list(v) for k,v in itertools.groupby(l)]
You're overcomplicating this.
What you want to do is: for each value, if it's the same as the last value, just append it to the list of last values; otherwise, create a new list. You can translate that English directly to Python:
new_list = []
for value in old_list:
if new_list and new_list[-1][0] == value:
new_list[-1].append(value)
else:
new_list.append([value])
There are even simpler ways to do this if you're willing to get a bit more abstract, e.g., by using the grouping functions in itertools. But this should be easy to understand.
If you really need to do this with a while loop, you can translate any for loop into a while loop like this:
for value in iterable:
do_stuff(value)
iterator = iter(iterable)
while True:
try:
value = next(iterator)
except StopIteration:
break
do_stuff(value)
Or, if you know the iterable is a sequence, you can use a slightly simpler while loop:
index = 0
while index < len(sequence):
value = sequence[index]
do_stuff(value)
index += 1
But both of these make your code less readable, less Pythonic, more complicated, less efficient, easier to get wrong, etc.
You can do that using numpy too:
import numpy as np
N = np.array([1,2,2,3,3,3,4,4,4,4,5,5,5,5,5])
counter = np.arange(1, np.alen(N))
L = np.split(N, counter[N[1:]!=N[:-1]])
The advantage of this method is when you have another list which is related to N and you want to split it in the same way.
Another slightly different solution that doesn't rely on itertools:
#!/usr/bin/env python
def group(items):
"""
groups a sorted list of integers into sublists based on the integer key
"""
if len(items) == 0:
return []
grouped_items = []
prev_item, rest_items = items[0], items[1:]
subgroup = [prev_item]
for item in rest_items:
if item != prev_item:
grouped_items.append(subgroup)
subgroup = []
subgroup.append(item)
prev_item = item
grouped_items.append(subgroup)
return grouped_items
print group([1,2,2,3,3,3,4,4,4,4,5,5,5,5,5])
# [[1], [2, 2], [3, 3, 3], [4, 4, 4, 4], [5, 5, 5, 5, 5]]

concatenate an arbitrary number of lists in a function in Python

I hope to write the join_lists function to take an arbitrary number of lists and concatenate them. For example, if the inputs are
m = [1, 2, 3]
n = [4, 5, 6]
o = [7, 8, 9]
then we I call print join_lists(m, n, o), it will return [1, 2, 3, 4, 5, 6, 7, 8, 9]. I realize I should use *args as the argument in join_lists, but not sure how to concatenate an arbitrary number of lists. Thanks.
Although you can use something which invokes __add__ sequentially, that is very much the wrong thing (for starters you end up creating as many new lists as there are lists in your input, which ends up having quadratic complexity).
The standard tool is itertools.chain:
def concatenate(*lists):
return itertools.chain(*lists)
or
def concatenate(*lists):
return itertools.chain.from_iterable(lists)
This will return a generator which yields each element of the lists in sequence. If you need it as a list, use list: list(itertools.chain.from_iterable(lists))
If you insist on doing this "by hand", then use extend:
def concatenate(*lists):
newlist = []
for l in lists: newlist.extend(l)
return newlist
Actually, don't use extend like that - it's still inefficient, because it has to keep extending the original list. The "right" way (it's still really the wrong way):
def concatenate(*lists):
lengths = map(len,lists)
newlen = sum(lengths)
newlist = [None]*newlen
start = 0
end = 0
for l,n in zip(lists,lengths):
end+=n
newlist[start:end] = list
start+=n
return newlist
http://ideone.com/Mi3UyL
You'll note that this still ends up doing as many copy operations as there are total slots in the lists. So, this isn't any better than using list(chain.from_iterable(lists)), and is probably worse, because list can make use of optimisations at the C level.
Finally, here's a version using extend (suboptimal) in one line, using reduce:
concatenate = lambda *lists: reduce((lambda a,b: a.extend(b) or a),lists,[])
One way would be this (using reduce) because I currently feel functional:
import operator
from functools import reduce
def concatenate(*lists):
return reduce(operator.add, lists)
However, a better functional method is given in Marcin's answer:
from itertools import chain
def concatenate(*lists):
return chain(*lists)
although you might as well use itertools.chain(*iterable_of_lists) directly.
A procedural way:
def concatenate(*lists):
new_list = []
for i in lists:
new_list.extend(i)
return new_list
A golfed version: j=lambda*x:sum(x,[]) (do not actually use this).
You can use sum() with an empty list as the start argument:
def join_lists(*lists):
return sum(lists, [])
For example:
>>> join_lists([1, 2, 3], [4, 5, 6])
[1, 2, 3, 4, 5, 6]
Another way:
>>> m = [1, 2, 3]
>>> n = [4, 5, 6]
>>> o = [7, 8, 9]
>>> p = []
>>> for (i, j, k) in (m, n, o):
... p.append(i)
... p.append(j)
... p.append(k)
...
>>> p
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>
This seems to work just fine:
def join_lists(*args):
output = []
for lst in args:
output += lst
return output
It returns a new list with all the items of the previous lists. Is using + not appropriate for this kind of list processing?
Or you could be logical instead, making a variable (here 'z') equal to the first list passed to the 'join_lists' function
then assigning the items in the list (not the list itself) to a new list to which you'll then be able add the elements of the other lists:
m = [1, 2, 3]
n = [4, 5, 6]
o = [7, 8, 9]
def join_lists(*x):
z = [x[0]]
for i in range(len(z)):
new_list = z[i]
for item in x:
if item != z:
new_list += (item)
return new_list
then
print (join_lists(m, n ,o)
would output:
[1, 2, 3, 4, 5, 6, 7, 8, 9]

Categories

Resources