How can I append values to a list without using the for-loop?
I want to avoid using the loop in this fragment of code:
count = []
for i in range(0, 6):
print "Adding %d to the list." % i
count.append(i)
The result must be:
count = [0, 1, 2, 3, 4, 5]
I tried different ways, but I can't manage to do it.
Range:
since range returns a list you can simply do
>>> count = range(0,6)
>>> count
[0, 1, 2, 3, 4, 5]
Other ways to avoid loops (docs):
Extend:
>>> count = [1,2,3]
>>> count.extend([4,5,6])
>>> count
[1, 2, 3, 4, 5, 6]
Which is equivalent to count[len(count):len(count)] = [4,5,6],
and functionally the same as count += [4,5,6].
Slice:
>>> count = [1,2,3,4,5,6]
>>> count[2:3] = [7,8,9,10,11,12]
>>> count
[1, 2, 7, 8, 9, 10, 11, 12, 4, 5, 6]
(slice of count from 2 to 3 is replaced by the contents of the iterable to the right)
Use list.extend:
>>> count = [4,5,6]
>>> count.extend([1,2,3])
>>> count
[4, 5, 6, 1, 2, 3]
You could just use the range function:
>>> range(0, 6)
[0, 1, 2, 3, 4, 5]
For an answer without extend...
>>> lst = [1, 2, 3]
>>> lst
[1, 2, 3]
>>> lst += [4, 5, 6]
>>> lst
[1, 2, 3, 4, 5, 6]
List comprehension
>>> g = ['a', 'b', 'c']
>>> h = []
>>> h
[]
>>> [h.append(value) for value in g]
[None, None, None]
>>> h
['a', 'b', 'c']
You can always replace a loop with recursion:
def add_to_list(_list, _items):
if not _items:
return _list
_list.append(_items[0])
return add_to_list(_list, _items[1:])
>>> add_to_list([], range(6))
[0, 1, 2, 3, 4, 5]
Related
Note: I know there is probably an answer for this on StackOverflow already, I just can't find it.
I need to do this:
>>> lst = [1, 2, 3, 4, 5, 6]
>>> first_two = lst.magic_pop(2)
>>> first_two
[1, 2]
>>> lst
[3, 4, 5, 6]
Now magic_pop doesn't exist, I used it just to show an example of what I need. Is there a method like magic_pop that would help me to do everything in a pythonic way?
Do it in two steps. Use a slice to get the first two elements, then remove that slice from the list.
first_list = lst[:2]
del lst[:2]
If you want a one-liner, you can wrap it in a function.
def splice(lst, start = 0, end = None):
if end is None:
end = len(lst)
partial = lst[start:end]
del lst[start:end]
return partial
first_list = splice(lst, end = 2)
One option would be using slices
def func(lst: list, n: int) -> tuple:
return lst[:n], lst[n:]
lst = [1, 2, 3, 4, 5, 6]
first_two, lst = func(lst, 2)
print(lst)
# [3, 4, 5, 6]
Alternative, here is a kafkaesque approach using builtins:
def func(lst: list, i: int) -> list:
return list(map(lambda _: lst.pop(0), range(i)))
lst = list(range(10))
first_two = func(lst, 2)
print(first_two)
# [0, 1]
print(lst)
# [2, 3, 4, 5, 6, 7, 8, 9]
Try:
lst = [1, 2, 3, 4, 5, 6]
first_two, lst = lst[:2], lst[2:]
print(first_two)
print(lst)
Prints:
[1, 2]
[3, 4, 5, 6]
You can just create a lambda function to do this.
magic_pop = lambda x,y:(x[:y],x[y:]) if y<len(lst) else x
magic_pop(lst,3)
Out[8]: ([1, 2, 3], [4, 5, 6])
Say I have [1, 2, 3, 4, 5, 6]. And I want [3, 4, 5, 6].
Currently I'm doing:
l = [1, 2, 3, 4, 5, 6]
l[-(len(l) - n):]
I'm not familiar with Python style, but this seems pretty hack-y.
Yes, by slicing:
>>> n = 2
>>> l = [1, 2, 3, 4, 5, 6]
>>> l[n:]
[3, 4, 5, 6]
Read the tutorial here to have a further understanding on how to manipulate Python data structures that support slicing.
Get creative and put it in a function, as mentioned in the comments:
def slice_it(l, n):
return l[n:]
demo:
>>> slice_it(l, 2)
[3, 4, 5, 6]
And as a lambda, as shown in the comments:
sliced_list = lambda l, n: l[n:]
demo:
>>> sliced_list(l, 2)
[3, 4, 5, 6]
You can use positive int as slice lower bound:
l = [1, 2, 3, 4, 5, 6]
l[n:]
You can just l[n:], rather than using negative indexing with the full length of the list.
For example, if len(l) == 6 then:
l[2:] == l[-4:]
Keep in mind #idjaw has a much better answer,
You can also use list comprehensions, like so:
>>> l = [1, 2, 3, 4, 5, 6]
>>> n = 3
>>> l = [x + 1 for x in range(len(l)) if x >= n]
>>> l
[4, 5, 6]
What will be the logic or code of this problem? The reverse() function does not take any argument and list[::-1] is also the same. How to do it in easy way?
Example, given:
list = [1,5,4,3,2,6]
Reversing 5...2, the output will be:
list = [1,2,3,4,5,6]
You could use list slice assignment, which modifies the list in-place:
>>> L = [1, 5, 4, 3, 2, 6]
>>> L[1:5] = L[4:0:-1]
>>> L
[1, 2, 3, 4, 5, 6]
You can reassign the slice of the list to that same slice in reverse
l = [1,5,4,3,2,6]
l[1:5] = l[1:5][::-1]
print(l)
#[1, 2, 3, 4, 5, 6]
You could do something like this:
l = [1,5,4,3,2,6]
index5 = l.index(5)
index2 = l.index(2)
l[index5:index2+1] = l[index2:index5-1:-1]
If you want it to be more explicit, you could use reversed:
l[index5:index2+1] = reversed(l[index5:index2+1])
Edit: Sorry, I misunderstood your question.
>>> l = [1, 5, 4, 3, 2, 6]
>>> temp = l[1:5]
>>> temp.reverse()
>>> l[1:5] = temp
>>> l
>>> [1, 2, 3, 4, 5, 6]
What is the best way to do this:
>>> replace2([1, 2, 3, 4, 5, 6])
[2, 1, 4, 3, 6, 5]
def replace2inplace(lst):
lst[1::2], lst[::2] = lst[::2], lst[1::2]
This uses slice assignment and slice step sizes to swap every pair in the list around, in-place:
>>> somelst = [1, 2, 3, 4, 5, 6]
>>> replace2inplace(somelst)
>>> somelst
[2, 1, 4, 3, 6, 5]
Otherwise you could use some itertools tricks:
from itertools import izip, chain
def replace2copy(lst):
lst1, lst2 = tee(iter(lst), 2)
return list(chain.from_iterable(izip(lst[1::2], lst[::2])))
which gives:
>>> replace2([1, 2, 3, 4, 5, 6])
[2, 1, 4, 3, 6, 5]
with the list() call optional; if you only need to loop over the result the generator is enough:
from itertools import izip, chain, islice, tee
def replace2gen(lst):
lst1, lst2 = tee(iter(lst))
return chain.from_iterable(izip(islice(lst1, 1, None, 2), islice(lst2, None, None, 2)))
for i in replace2gen([1, 2, 3, 4, 5, 6]):
print i
where replace2gen() can take arbitrary iterators too.
Out-of-place version:
def replace2(lst):
return [x for pair in zip(lst[1::2], lst[::2]) for x in pair]
My choice:
x = range(1,7)
res = [e for e in itertools.chain(*zip(x[1::2],x[0::2]))]
>>> a = [1, 2, 3, 4, 5, 6]
>>> sum([[x+1,x] for x in a if x&1 == True],[])
[2, 1, 4, 3, 6, 5]
EDIT: Some further explanation was requested:
The code steps through each element in the list a and, if the element is odd (x&1 == True) it puts that element and the next element into a list in reverse order ([x+1,x]).
With out the sum(...,[]) function we would have
[[2, 1], [4, 3], [6, 5]]
The sum(...,[]) function removes the internal square brackets giving
[2, 1, 4, 3, 6, 5]
This can be done more generally by using the index of the list rather than its value:
>>> a = [1, 2, 3, 4, 5, 6]
>>> sum([[a[x],a[x-1]] for x in range(len(a)) if x&1 == True],[])
[2, 1, 4, 3, 6, 5]
However, this will remove the last element of the list if its length is not even.
Can't figure out how to do this in a pretty way :
I have a list of n elements,
I want to access every m elements of the list.
For example : [1, 2, 3, 4, 5] and m = 2 would give
[2, 4]
I can do it simply with a loop, but ins't there a more "pythonic" way?
Thanks by advance !
EDIT :
Seems like I forgot something.
I want, not only get those values but modify them.
I tried slicing a[::2] = 3, but it doesn't work. . .
I'm searching for something similar
Slicing syntax does this for you:
>>> my_list = range(10)
>>> my_list
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> my_list[::2]
[0, 2, 4, 6, 8]
>>> my_list[1::2]
[1, 3, 5, 7, 9]
Here's a way to wrap a list to get the original assignment behavior you wanted, but I'm not sure I'd recommend it:
class AssignableSlice(list):
def __setitem__(self, i, v):
if isinstance(i, slice):
for ii in xrange(*i.indices(len(self))):
self[ii] = v
else:
super(AssignableSlice, self).__setitem__(i, v)
a = AssignableSlice(range(10))
print a
a[::2] = 3
print a
a[1::3] = 99
print a
produces:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[3, 1, 3, 3, 3, 5, 3, 7, 3, 9]
[3, 99, 3, 3, 99, 5, 3, 99, 3, 9]
Ned's answer shows how to use slices to access a portion of the list. You can also assign to a slice, but you need to assign a list to the slice, for example:
>>> my_list = range(5)
>>> my_list
[0, 1, 2, 3, 4]
>>> my_list[::2]
[0, 2, 4]
>>> my_list[::2] = [0, 0, 0]
>>> my_list
[0, 1, 0, 3, 0]
Note that when the step in your slice is anything besides the default of 1 the list that you assign needs to be the same length, however with a default step you can actually change the size of the list with slice assignment:
>>> my_list = range(5)
>>> my_list
[0, 1, 2, 3, 4]
>>> my_list[:1]
[0]
>>> my_list[:1] = [4, 3, 2] # replace the first item with 3 new items
>>> my_list
[4, 3, 2, 1, 2, 3, 4]
>>> my_list[2:5]
[2, 1, 2]
>>> my_list[2:5] = [] # remove the middle three items from the list
>>> my_list
[4, 3, 3, 4]
I juste found a way to do what I want using slicing.
The following :
candidates[::2] = [1] * len(candidates[::2])
will replace every 2 elements of candidates by 1