I have a list
A = [1,6,3,8,5,5,2,1,2,10]
I want to repeat the numbers in this like:
A = [1,6,6,6,6,6,6,3,3,3,8,8,8,8,8,8,8,8,..... so on]
i.e 1 repeat once, 6 repeat six times, 3 repeat thrice and so on....
I tried with:
B=np.concatenate([([x]*x) for x in A], axis=0)
but it multiplying the corresponding number and I am getting this result:
B = [1,36,36,36,36,36,36,9,9,9,.....so on]
when I am doing:
B=np.concatenate([([x]*3) for x in A], axis=0)
this giving me:
B = [1,1,6,6,3,3,8,8... so on]
what wrong I am doing here?
You can perform this operation using numpy without using a for loop.
np.repeat(a, repeats) will repeat the input array a according to repeats which specify the number of repetitions for each element.
import numpy as np
A = [1,6,3,8,5,5,2,1,2,10]
B = np.repeat(A,A)
Output:
>>> array([ 1, 6, 6, 6, 6, 6, 6, 3, 3, 3, 8, 8, 8, 8, 8, 8, 8,
8, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 1, 2, 2, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10])
Using the repeat function of NumPy you can get the solution
import numpy as np
np.repeat(A, A)
You should use nested loop
l = [1, 6, 3]
nl = []
for number in l:
for i in range(number):
nl.append(number)
print(nl)
or using list comprehension
l = [1,6,3]
nl = [number for number in l for i in range(number)]
#[1, 6, 6, 6, 6, 6, 6, 3, 3, 3]
hello you can make this with the lib itertools:
import itertools
lst = [1,2,3,4,5]
# [1, 2, 3, 4, 5]
list(itertools.chain.from_iterable(itertools.repeat(x, x) for x in lst))
#[1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5]
You have a list of integers, to which the multiplication means arithmetic multiplication. You need to convert them into strings.
A = [1,6,3,8,5,5,2,1,2,10]
new_A = [x * str(x) for x in A]
which is called list comprehension, being a much cleaner/pythonic way of:
for x in A:
new_A.append(x * str(x))
B = np.concatenate([[a]*a for a in A])
>>> array([ 1, 6, 6, 6, 6, 6, 6, 3, 3, 3, 8, 8, 8, 8, 8, 8, 8,
8, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 1, 2, 2, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10])
nums = [1, 5, 4]
res = []
for num in nums:
res.extend([num] * num)
print(res)
# [1, 5, 5, 5, 5, 5, 4, 4, 4, 4]
Related
I'm looking to keep the individual elements of a list repeating for x number of times, but can only see how to repeat the full list x number of times.
For example, I want to repeat the list [3, 5, 1, 9, 8] such that if x=12, then I want to produce tthe following list (i.e the list continues to repeat in order until there are 12 individual elements in the list:
[3, 5, 1, 9, 8, 3, 5, 1, 9, 8, 3, 5]
I can do the below but this is obviously not what I want and I'm unsure how to proceed from here.
my_list = [3, 5, 1, 9, 8]
x = 12
print(my_list * 12)
[3, 5, 1, 9, 8, 3, 5, 1, 9, 8, 3, 5, 1, 9, 8, 3, 5, 1, 9, 8, 3, 5, 1, 9, 8, 3, 5, 1, 9, 8, 3, 5, 1, 9, 8, 3, 5, 1, 9, 8, 3, 5, 1, 9, 8, 3, 5, 1, 9, 8, 3, 5, 1, 9, 8, 3, 5, 1, 9, 8]
Your code repeats list 12 times. You need to repeat list until length is matched. This can achieved using Itertools - Functions creating iterators for efficient looping
from itertools import cycle, islice
lis = [3, 5, 1, 9, 8]
out = list(islice(cycle(lis), 12))
print(out)
Gives #
[3, 5, 1, 9, 8, 3, 5, 1, 9, 8, 3, 5]
More pythonic #
Use a for loop to access each element in list and iterate over 'length' times. Repeat Ith element you access through loop in same list until length matches.
lis = [3, 5, 1, 9, 8]
length = 12
out = [lis[i%len(lis)] for i in range(length)]
print(out)
Gives ##
[3, 5, 1, 9, 8, 3, 5, 1, 9, 8, 3, 5]
There are multiple ways to go about it. If x is the final length desired and lst is the list (please do not use list as a variable name because it overwrites the builtin list function), then you can do :
lst = (lst * (1 + x // len(lst)))[:x]
This multiplies the list by the smallest number needed to get at least N elements, and then it slice the list to keep only the first N. For your example :
>>> lst = [3, 5, 1, 9, 8]
>>> x = 12
>>> (lst * (1 + x // len(lst)))[:x]
[3, 5, 1, 9, 8, 3, 5, 1, 9, 8, 3, 5]
You could also use a loop, for example :
index = 0
while len(lst) < x:
lst.append(lst[index])
index += 1
can you help me with this problem please?
I have to create a list of 50 random numbers from 1 to 10 where the odd numbers frequency is aproximately twice the even number frequency.
Try two list, one with 33 random odd numbers and the other with 17 random even numbers, and then merge the two lists.
Solution as simplified
import random
odd=[item for item in range(1,11,2)]
even=[item for item in range(2,11,2)]
# twice chance 50/3 ~17 odd=33 even=17
random_even=[random.choice(even) for _ in range(17)]
random_odd=[random.choice(odd) for _ in range(33)]
random_number=random_even+random_odd # sum
random.shuffle(random_number) # messing up order
print("even",len(random_even),"odd",len(random_odd)) #check len
print("len list : ",len(random_number))#check len
print(random_number)#show list
random.choices has an argument weights, which can makes the odd number roughly twice as many as the even number:
>>> nums = range(1, 11)
>>> random.choices(nums, weights=[2 / 3, 1 / 3] * 5, k=50)
[7, 4, 4, 2, 1, 1, 7, 9, 6, 9, 3, 9, 9, 5, 9, 3, 2, 1, 9, 10, 9, 3, 7, 5, 3, 8, 8, 10, 9, 5, 2, 9, 9, 6, 5, 5, 10, 5, 6, 5, 1, 3, 3, 2, 5, 6, 5, 5, 5, 2]
>>> sum(i % 2 == 0 for i in _)
16
>>> (50 - 16) / 16
2.125
If you have strict requirements on their quantitative relationship, you can generate two lists, concatenate and shuffle:
>>> n_even = 50 // 3
>>> n_odd = 50 - n_even
>>> rand = random.choices(nums[::2], k=n_odd) + random.choices(nums[1::2], k=n_even)
>>> random.shuffle(rand)
>>> rand
[2, 10, 5, 8, 7, 10, 3, 5, 1, 7, 8, 10, 7, 5, 3, 9, 3, 10, 3, 2, 1, 10, 9, 8, 7, 6, 1, 1, 8, 1, 5, 4, 9, 9, 2, 1, 5, 1, 4, 7, 1, 2, 5, 7, 7, 1, 7, 1, 1, 5]
I start with a list of integers:
A = [ 1, 2, 5, 3, 4, 6, 7, 8 ]
After a shuffle, I would like some elements (say 3, 4 and 5) to preserve their order of occurrence in A while the rest of the elements are free to be randomly shuffled. Something like:
Outcome #1:
A = [ 5, 2, 3, 1, 8, 4, 6, 7 ]
-or-
Outcome #2:
A = [ 7, 5, 6, 1, 3, 4, 8, 2 ]
-but not-
Outcome #3 (invalid outcome)
A = [7, 4, 6, 1, 3, 5, 8, 2]
Appreciate all suggestions!
Extract the elements you want to maintain relative ordering among, shuffle as normal, then glue the lists back together by randomly picking indexes for the "kept" elements to be inserted. All operations are linear if you use sets for speeding up in operations, which I didn't bother with. Ordering of the keep list matters.
>>> import random
>>> L = [1, 2, 5, 3, 4, 6, 7, 8]
>>> keep = [2, 3, 4]
>>> kept = [L[i] for i in keep][::-1]
>>> unkept = [x for i, x in enumerate(L) if i not in keep]
>>> random.shuffle(unkept)
>>> idxes = random.sample(list(range(len(L))), k=len(keep))
>>> result = [kept.pop() if i in idxes else unkept.pop() for i in range(len(L))]
>>> result
[6, 5, 3, 8, 4, 1, 7, 2]
Random tests:
import random
def shuffle_with_fixed_order(L, keep):
kept = [L[i] for i in keep][::-1]
unkept = [x for i, x in enumerate(L) if i not in keep]
random.shuffle(unkept)
idxes = random.sample(list(range(len(L))), k=len(keep))
return [kept.pop() if i in idxes else unkept.pop() for i in range(len(L))]
if __name__ == "__main__":
for _ in range(5000):
L = list(range(50))
random.shuffle(L)
keep = sorted(random.sample(L, k=20))
shuffled = shuffle_with_fixed_order(L, keep)
new_locs = [shuffled.index(L[i]) for i in keep]
assert all(x < y for x, y in zip(new_locs, new_locs[1:]))
This is one approach using random module
Ex:
import random
A = [ 1, 2, 5, 3, 4, 6, 7, 8 ]
result = A[2:5]
del A[2:5]
while A:
l = len(A)
result.insert(random.randint(0, l), A.pop(random.randrange(l)))
print(result)
Demo
def rand_shfl(lst):
result = lst[2:5]
del lst[2:5]
while A:
l = len(A)
result.insert(random.randint(0, l), A.pop(random.randrange(l)))
return result
for _ in range(10):
A = [ 1, 2, 5, 3, 4, 6, 7, 8 ]
print((rand_shfl(A)))
Output:
[1, 7, 6, 5, 8, 3, 4, 2]
[8, 1, 2, 7, 5, 3, 6, 4]
[8, 6, 7, 2, 1, 5, 3, 4]
[1, 7, 2, 8, 5, 3, 4, 6]
[6, 8, 7, 5, 1, 3, 4, 2]
[7, 2, 5, 6, 1, 3, 4, 8]
[1, 8, 5, 2, 3, 4, 6, 7]
[5, 7, 1, 6, 3, 8, 4, 2]
[1, 5, 7, 3, 2, 4, 8, 6]
[8, 2, 7, 6, 5, 3, 4, 1]
Probably below will work for you
import random
lst=[1, 2, 5, 3, 4, 6, 7, 8]
s_lst = {5:0,3:0,4:0}
idx_lst = [random.randint(0, len(lst)) for i in range(len(s_lst))]
idx_lst.sort()
for i, s in enumerate(s_lst.keys()):
s_lst[s] = idx_lst[i]
lst.remove(s)
random.shuffle(lst)
for k, v in s_lst.items():
lst.insert(v, k)
print(lst)
What's the most pythonic way of performing an arithmetic operation on every nth value in a list? For example, if I start with list1:
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
I would like to add 1 to every second item, which would give:
list2 = [1, 3, 3, 5, 5, 7, 7, 9, 9, 11]
I've tried:
list1[::2]+1
and also:
for x in list1:
x=2
list2 = list1[::x] + 1
You could use slicing with a list comprehension as follows:
In [26]: list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
In [27]: list1[1::2] = [x+1 for x in list1[1::2]]
In [28]: list1
Out[28]: [1, 3, 3, 5, 5, 7, 7, 9, 9, 11]
numpy allows you to use += operation with slices too:
In [15]: import numpy as np
In [16]: l = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
In [17]: l[1::2] += 1
In [18]: l
Out[18]: array([ 1, 3, 3, 5, 5, 7, 7, 9, 9, 11])
Use enumerate and a list comprehension
>>> list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> [v+1 if i%2!=0 else v for i,v in enumerate(list1)]
[1, 3, 3, 5, 5, 7, 7, 9, 9, 11]
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for i in range(1, len(list1), 2):
list1[i] +=1
print(list1)
using i%2 seems not very efficient
Try this:
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for i in range(1,len(list1),2):
list1[i] += 1
You can create an iterator representing the delta (itertools.cycle([0, 1]) and then add its elements to your existing list.
>>> list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> [a + b for a,b in zip(list1, itertools.cycle([0,1]))]
[1, 3, 3, 5, 5, 7, 7, 9, 9, 11]
>>>
a = [i for i in range(1,11)]
#a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b = [a[i]+1 if i%2==1 else a[i] for i in range(len(a))]
#b = [1, 3, 3, 5, 5, 7, 7, 9, 9, 11]
I have created a two functions which sorts integers from lowest value to highest then back to low. Does this type of sort exist? Anyways, I have the following two sorting functions which I have created which produce the same output. I was wondering which is the most efficient of the two? Are there any improvements I can make to either?
sortMiddleMax1
Create a new reverse sorted list of original
Start from index 1 to length of list step by 2
sortMiddleMax2
Sorts the list in-place
Start from last index to 0 step by 2
I tried to make the second more efficient than the first. I did not create a new list in memory and I appended to the end instead of pushing the whole list right. Am I correct in this assumption?
Functions
def sortMiddleMax1(aList=None, verbose=False):
if aList == None or len(aList) < 2:
return aList
else:
sList = sorted(x, key=None, reverse=True)
if verbose: print sList
index = 1
while index < len(sList):
tmp = sList[index]
del sList[index]
sList.insert(0, tmp)
index+=2
if verbose: print sList
return sList
def sortMiddleMax2(aList=None, verbose=False):
if aList == None or len(aList) < 2:
return aList
else:
aList.sort()
if verbose: print aList
index = len(aList)-1
while index > 0:
tmp = aList[index]
del aList[index]
aList.append(tmp)
index-=2
if verbose: print aList
return aList
Main
x = [1,4,6,8,3,5,7,1,5,8,3,9,2,8]
print '############# sortMiddleMax1 #############'
x1 = sortMiddleMax1(x, True)
print '############# sortMiddleMax2 #############'
x2 = sortMiddleMax2(x, True)
Output
############# sortMiddleMax1 #############
[9, 8, 8, 8, 7, 6, 5, 5, 4, 3, 3, 2, 1, 1]
[8, 9, 8, 8, 7, 6, 5, 5, 4, 3, 3, 2, 1, 1]
[8, 8, 9, 8, 7, 6, 5, 5, 4, 3, 3, 2, 1, 1]
[6, 8, 8, 9, 8, 7, 5, 5, 4, 3, 3, 2, 1, 1]
[5, 6, 8, 8, 9, 8, 7, 5, 4, 3, 3, 2, 1, 1]
[3, 5, 6, 8, 8, 9, 8, 7, 5, 4, 3, 2, 1, 1]
[2, 3, 5, 6, 8, 8, 9, 8, 7, 5, 4, 3, 1, 1]
[1, 2, 3, 5, 6, 8, 8, 9, 8, 7, 5, 4, 3, 1]
############# sortMiddleMax2 #############
[1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 8, 8, 8, 9]
[1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 8, 8, 8, 9]
[1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 8, 8, 9, 8]
[1, 1, 2, 3, 3, 4, 5, 5, 6, 8, 8, 9, 8, 7]
[1, 1, 2, 3, 3, 4, 5, 6, 8, 8, 9, 8, 7, 5]
[1, 1, 2, 3, 3, 5, 6, 8, 8, 9, 8, 7, 5, 4]
[1, 1, 2, 3, 5, 6, 8, 8, 9, 8, 7, 5, 4, 3]
[1, 2, 3, 5, 6, 8, 8, 9, 8, 7, 5, 4, 3, 1]
You can use Python's extended slicing. [::2] means take every second element. [::-2] means take every second element from the end and work backwards. Here the first slice starts at 0 for even length list and 1 for odd length lists
>>> x = [1, 4, 6, 8, 3, 5, 7, 1, 5, 8, 3, 9, 2, 8]
>>> x = sorted(x)
>>> x[len(x)%2::2] + x[::-2]
[1, 2, 3, 5, 6, 8, 8, 9, 8, 7, 5, 4, 3, 1]
You can use list slice to get the result without for loop:
x = sorted([1,4,6,8,3,5,7,1,5,8,3,9,2,8])
x2 = x[::2] + x[1::2][::-1]
I suspect your two current versions perform exactly the same. However, they both can be improved by using slices to get at the values in the list, rather than by deleting and inserting values.
Each del and each insert is O(N) and you're doing N/2 of each, so the sort will be O(N^2). Slicing is O(N) as well, but only needs to be done twice. The time taken for the sort O(N log N) will dominate, asymptotically.
def sortMiddle3(aList):
s = sorted(aList) # sort the provided list
# now take the even indexed items, followed by the odd indexes in reverse
if len(s) % 2 == 0: # is the number of items even?
return s[::2] + s[-1::-2] # if so, the last item has an odd index
else:
return s[::2] + s[-2::-2]
Example output:
>>> x = [1,4,6,8,3,5,7,1,5,8,3,9,2,8]
>>> sortMiddle3(x)
[1, 2, 3, 5, 6, 8, 8, 9, 8, 7, 5, 4, 3, 1]