How can I repeat elements in place in an array in Python?
Or similarly, something more simple than this:
drange = [];
for i in xrange(j):
drange.append(i);
drange.append(i);
It should produce: [0, 0, 1, 1, 2, 2, ... j-1, j-1]
>>> j = 3
>>> drange = []
>>> for i in xrange(j):
... drange.extend([i]*2)
...
>>> drange
[0, 0, 1, 1, 2, 2]
or as a list comprehension
>>> drange = [i for i in xrange(j) for k in range(2)]
>>> drange
[0, 0, 1, 1, 2, 2]
In some cases this method can also be appropriate
>>> drange = [i//2 for i in xrange(j*2)]
>>> drange
[0, 0, 1, 1, 2, 2]
An answer using numpy
>>> import numpy as np
>>> j = 3
>>> np.repeat(np.array(xrange(j)), 2)
array([0, 0, 1, 1, 2, 2])
Use list comprehension then flatten the list:
>>> sum([ [i]*2 for i in xrange(5)],[])
[0, 0, 1, 1, 2, 2, 3, 3, 4, 4]
Here is a two-line alternative.
base= [2*[i] for i in range(5)]
drange = [item for x in base for item in x]
Related
I have this list:
l = [0, 1, 2]
and obviously l[0] = 0, l[1] = 1, l[2] = 2,
but I want l[3] to be = to 0, l[4] = 1, l[5] = 2 and so on...
you can use the modulus operator to cycle through the elements of the list.
l[index % 3]
In general:
lst = [0, 1, 2]
lst[index % len(lst)]
Depending on what you're trying to do, you can "multiply" a list to create a longer, repeating list of the original. Alternatively, you can create an iterator that just yields the same sequence of numbers indefinitely:
>>> numbers = [0, 1, 2] * 5
>>> numbers
[0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2]
>>> from itertools import cycle
>>> number_iter = cycle([0, 1, 2])
>>> next(number_iter)
0
>>> next(number_iter)
1
>>> next(number_iter)
2
>>> next(number_iter)
0
>>> next(number_iter)
1
>>> next(number_iter)
2
>>>
Input
l = [0, 0, 1, 2, 3]
I want to add 1 to index range from 2 to 3
so output should be
l = [0, 0, 2, 3, 3]
l[2:3] = l[2:3] + 1
The easiest way would be to use numpy, it's quite optimized and uses C/C++ loops under the hood, so it's blazingly fast:
>>> import numpy as np
>>> a = [0, 0, 1, 2, 3]
>>> b = np.array(a)
>>> b[2:4] += 1
>>> b
array([0, 0, 2, 3, 3])
>>>
You can try this:
for i in range(2, 4):
l[i] += 1
A possible solution can make use of list-comprehension:
l[2:4] = [x+1 for x in l[2:4]]
For a hilariously overblown solution:
from operator import add
l = [0, 0, 1, 2, 3]
deltas = [0, 0, 1, 1, 1]
result = list(map(add, l, deltas))
note that this does not modify l, but creates a new list in result
Say i have two arrays:
a = [1, 1, 1] and
b = [0, 0]
I want to concatenate these randomly in a seperate variable c, until i reach some desired length of c. So something like:
N = 10
c = random_concatenating((a, b), N)
[1, 1, 1, 0, 0, 1, 1, 1, 0, 0]
A verbose version:
import random
a = [1, 1, 1]
b = [0, 0]
N = 10
def random_concatenating(iterable, n):
rv = []
l = [*iterable]
print(l)
while len(rv) < n:
rv.extend(random.choice(l))
return rv[:n]
c = random_concatenating((a, b), N)
print(c)
Prints (for example):
[1, 1, 1, 0, 0, 1, 1, 1, 1, 1]
You can use itertools.cycle to repeat the lists as many times as you need then slice them to the needed list
>>> from itertools import cycle, islice
>>> a = [1, 1, 1]
>>> b = [0, 0]
>>> N = 10
>>> list(islice(cycle(a+b), N))
[1, 1, 1, 0, 0, 1, 1, 1, 0, 0]
This is one approach. Using random.choice
import random
a = [1, 1, 1]
b = [0, 0]
N = 10
foo = a + b
c = []
for i in range(N):
c.append(random.choice(foo))
print(c)
Output:
[0, 1, 1, 1, 1, 0, 1, 1, 1, 1]
One-line
c = [random.choice(foo) for i in range(N)]
This question already has answers here:
python: most elegant way to intersperse a list with an element
(15 answers)
Closed 6 years ago.
I have a list like
[1, 2, 3, 4, 5]
and I want to add zeroes at odd indexes:
[1, 0, 2, 0, 3, 0, 4, 0, 5]
My first thought was to create a list with zeroes and replace them with the values from the original list.
listOfZeros = [0] * (2*len(list)-1)
j = 0
for i in range(0, len(listOfZeros)):
if (i%2 == 0):
listOfZeros[i] = h_temp[j]
j += 1
This actually works, but I do dislike for loops and adding another counter j. Isn't there a better way by using slicing?
You can use insert(). Looking at your output, assuming you are not counting index 0 as even.
a = [1,2,3,4,5]
for x in range(len(a)):
a.insert(2*x+1, 0)
one way is by using zip:
a = [1, 2, 3, 4, 5]
d = [x for t in zip (a, [0] * len(a)) for x in t][:-1]
When you use zip, you create list of tuples.
a = [1,2,3,4,5]
b = [0,0,0,0,0]
c = zip(a,b)
#zip (a,b) creates [(1,0),(2,0),(3,0),(4,0),(5,0)]
Then you loop over the set of tuples to arrange them into list:
d = [x for t in c for x in t] #creates [1,0,2,0,3,0,4,0,5,0]
and cut the last element (since you end with 5)
[x for t in c for x in t][:-1] #take out the last 0
#resulting in [1,0,2,0,3,0,4,0,5]
then you are done.
You can do it with a generator:
def zero_on_odd(mylist):
for i in mylist:
yield i
yield 0
a = [1, 2, 3]
with_zeros = list(zero_on_odd(a))[:-1]
If you want to go functional...
from itertools import chain, repeat
_list = [1,2,3,4,5]
list(chain(*zip(_list, repeat(0))))[:-1]
# [1, 0, 2, 0, 3, 0, 4, 0, 5]
If you want to be silly...
[int(i) for i in '0'.join(str(i) for i in _list)]
# still [1, 0, 2, 0, 3, 0, 4, 0, 5]
Or, if you want to be functional AND silly...
map(int, '0'.join(map(str, _list)))
# really, it's still [1, 0, 2, 0, 3, 0, 4, 0, 5]
# except in Python 3.X, there it's a map object...
But, you should probably opt for one of the custom generator solutions.
For the fun of it, here is an itertools solution:
from itertools import islice, chain
data = [1,2,3,4,5]
print list(islice(chain.from_iterable((x, 0) for x in data), 0, 2 * len(data)-1))
Giving:
[1, 0, 2, 0, 3, 0, 4, 0, 5]
Another zip way:
>>> li
[1, 2, 3, 4, 5]
>>> [e for t in zip(li,[0]*(len(li)-1)) for e in t]+[li[-1]]
[1, 0, 2, 0, 3, 0, 4, 0, 5]
You can also use range and slice assignment:
>>> li=[1,2,3,4,5]
>>> for i in range(1,len(li)+len(li)-1, 2): li[i:i]=[0]
...
>>> li
[1, 0, 2, 0, 3, 0, 4, 0, 5]
And, a list comprehension:
>>> [li[i/2] if not i%2 else 0 for i in range(len(li)*2-1)]
[1, 0, 2, 0, 3, 0, 4, 0, 5]
A hacky way:
>>> ls1 = [1, 2, 3, 4, 5]
>>> ls2 = []
>>> list(ls2.extend([n, 0]) for n in ls1)
[None, None, None, None, None]
>>> ls2
[1, 0, 2, 0, 3, 0, 4, 0, 5, 0]
I know that I can interleave two python lists with:
[elem for pair in zip(*lists) for elem in pair]
Now I need to interleave a list with a fixed element like:
list = [1, 2, 3, 4]
# 🐍 python magic 🐍
output = [1, 0, 2, 0, 3, 0, 4]
One really straightforward solution is:
[elem for x in list for elem in (x, 0)][:-1]
You can try the following itertools magic:
>>> from itertools import repeat, chain, izip
>>> l = [1, 2, 3, 4]
>>> list(chain.from_iterable(izip(l[:-1], repeat(0)))) + l[-1:]
[1, 0, 2, 0, 3, 0, 4]
from itertools import izip, repeat
start = [1, 2, 3, 4]
print [i for j in izip(start, repeat(0)) for i in j][:-1]
Python's sum function can be used on arbitrary datatypes that support addition by setting the start parameter appropriately. (see docs)
input = [1, 2, 3, 4]
fixed = 0
output = sum([[elem, fixed] for elem in input], [])[:-1] # to drop the last `fixed`
Or if you don't like the idea of using the addition operator with lists:
input = [1, 2, 3, 4]
fixed = 0
output = []
for elem in input:
output.extend([elem, fixed])
output = output[:-1]
>>> lst = [1, 2, 3, 4]
>>> newlst = [0]*((len(lst) * 2) - 1)
>>> newlst[::2] = lst
>>> newlst
[1, 0, 2, 0, 3, 0, 4]
It may not be a one-liner, but it works. Furthermore, my time tests seem to show that it's the fastest solution so far. In function form, this is:
def interzero(lst):
newlst = [0]*((len(lst) * 2) - 1)
newlst[::2] = lst
return newlst
You could use the reduce function of functools.
>>> from functools import reduce
>>> reduce(lambda x, y: x + [y, 0], [1,2,3,4], [])[:-1]
[1, 0, 2, 0, 3, 0, 4]
>>> from itertools import chain
>>> lst = [1, 2, 3, 4]
>>> list(chain(*zip(lst, [0]*(len(lst)-1)))) + [lst[-1]]
[1, 0, 2, 0, 3, 0, 4]