Create a list with six sublists of random numbers - python

I'm totally new with Python; however, I would like to make a list of 6 sub-lists, each of which contains 4 random values between 0 and 30.
The answer should print like this:
lst[0] = [1,4,4,5]
lst[1] = [23,14,5,8]
...
lst[5] = [8,9,18,27]

Here is the simple one-liner that'll get it done:
from random import randint
rand_list = [[randint(0, 30) for i in range(4)] for n in range(6)]
>>>rand_list
[[28, 17, 5, 9],
[27, 29, 3, 8],
[18, 13, 4, 11],
[15, 12, 11, 19],
[17, 8, 22, 30],
[24, 6, 9, 1]]
If you want to get fancy, you can easily expand it into a function that will allow you to specify the list-sizes as inputs to the function:
def rand_lists(num_lists, num_vals):
return [[randint(0, 30) for i in range(num_vals)] for n in range(num_lists)]
>>> rand_lists(2, 7)
[[17, 8, 29, 2, 9, 26, 16],
[24, 22, 5, 10, 11, 0, 10]]

For a one-liner:
from random import randint
lst = [[randint(0, 30) for col in range(4)] for row in range(6)]
Which is equivalent to(in pure python):
lst = []
for row in range(6):
r = []
lst.append(r)
for col in range(4):
r.append(randint(0, 30))

Related

increment of list elements in a certain pattern

I have a list for example:
[1,2,3,4]
I want to have ten repeats of the list, and every element increase by 1 than the previous element like:
[1,2,3,4,2,3,4,5,3,4,5,6................40 elements]
Thanks for the previous answers!
The closest answer I got so far:
list = [1,2,3,4]
n = 4 #number of elements in the list
newList = [ ]
for i in range(10):
for element in list:
newList.append(element + i*n)
print(newList)
print(len(newList))
The output:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40]
40
temp = [1, 2, 3, 4]
lst = [i + j for i in range(9) for j in temp]
print(lst)
# which equals to this:
temp = [1, 2, 3, 4]
lst2 = []
for i in range(9):
for j in temp:
lst2.append(i + j)
print(lst2)
plz have a look. I don't think it goes upto [1,2,..40] , only goes upto[1,2,.. 14].
At each iteration you are increasing the value by 1 so, after 10 times repeating every no in the array will be increased by 10. So 4 will be 14 which will be the last element not 40.
Here's my code according to your requirement,
arr = [1,2,3,4]
answer = [ ]
for i in range(11):
for element in arr:
answer.append(element + i)
print(answer)

sum of elements in list, when an element can take two different values

I have a list of elements and want to get the sum of this list:
a = [4, 5, "X", "X"].
But X can be 2 different values, 2 or 3. So there are 4 sums of this list:
sum1 = sum([4, 5, 2, 2]) = 13
sum2 = sum([4, 5, 2, 3]) = 14
sum3 = sum([4, 5, 3, 2]) = 14
sum4 = sum([4, 5, 3, 3]) = 15
Basically I want to get a tuple (or list) of all possible sums of the list, like:
sums = (13, 14, 14, 15)
For an input list with 0 X, I want to get a tuple with 1 element, for a tuple with 1 X a tuple of 2 elements, with 2 X tuple with 4 elements...with n X a tuple of 2^n elements.
Similar to Michael's answer, also using itertools.product, but with a dictionary mapping elements to possible values. This might be more flexible, allowing placeholders in all positions and different values for different placeholders, and also makes the code a bit simpler IMHO.
>>> from itertools import product
>>> a = [4, 5, "X", "X"]
>>> vals = {"X": [2, 3]}
>>> [sum(p) for p in product(*[vals.get(x, [x]) for x in a])]
[13, 14, 14, 15]
You can use itertools.product and a list comprehension
from itertools import product
a = [4, 5, "X", "X"]
r = a.count('X')
[sum(a[:len(a)-r] + [*i]) for i in product([2,3], repeat=r)]
Output
[13, 14, 14, 15]
Testing with more cases
#test cases
for n in range(5):
a=[4,5, *['X']*n] # [4,5] .... [4,5,'X','X','X','X']
r = a.count('X')
print([sum(a[:len(a)-r] + [*i]) for i in product([2,3], repeat=r)])
Output
[9]
[11, 12]
[13, 14, 14, 15]
[15, 16, 16, 17, 16, 17, 17, 18]
[17, 18, 18, 19, 18, 19, 19, 20, 18, 19, 19, 20, 19, 20, 20, 21]

Python Reversing Certain Parts of Tuple

Suppose i have the following tuple as:
a = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)
What i want to do is reversing certain parts of the tuple.
For example 4 elements stays same and then 4 elements will be reversed.
I want to get the following result:
a = (1,2,3,4,8,7,6,5,9,10,11,12,16,15,14,13,17,18,19,20)
How can i achieve that (as pythonian kind of way)?
Thanks...
Tuples are immutable, however, by converting a to a list, in-place assignment can be performed:
a = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)
new_a = list(a)
for c, i in enumerate(range(0, len(a), 4)):
if c%2:
new_a[i:i+4] = new_a[i:i+4][::-1]
print(tuple(new_a))
Output:
(1, 2, 3, 4, 8, 7, 6, 5, 9, 10, 11, 12, 16, 15, 14, 13, 17, 18, 19, 20)
The direct, simple, readable answer (pythonic?):
a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
for n in range(0, len(a), 8):
a[n+4:n+8] = a[n+7:n+3:-1]
print(a)
Here's a generator-based solution. The benefits of doing it this way is that this solution doesn't require the input to be sliceable, so you can apply it to the output of functions like zip and map.
from itertools import zip_longest as zipl
from itertools import cycle, chain
_marker = object()
def cycle_map(iterable, func_iterable):
funcs = cycle(func_iterable)
for func, item in zip(funcs, iterable):
if func:
yield func(item)
else:
yield item
def reverse_filter(iterable, remove=_marker):
t = tuple(i for i in iterable if i is not remove)
return reversed(t)
def reverse_alternating(iterable, length=4):
chunks = zipl(*[iter(iterable)]*length, fillvalue=_marker)
funcs = (None, reverse_filter)
return chain.from_iterable(cycle_map(chunks, funcs))
a = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)
list(reverse_alternating(a))
# [1, 2, 3, 4, 8, 7, 6, 5, 9, 10, 11, 12, 16, 15, 14, 13, 17, 18, 19, 20]
Using list slicing.
Ex:
from itertools import chain
a = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)
res = [a[v:v+4] if i%2 == 0 else list(reversed(a[v:v+4])) for i, v in enumerate(range(0, len(a), 4))]
print(tuple(chain.from_iterable(res))) #Flatten list
Output:
(1, 2, 3, 4, 8, 7, 6, 5, 9, 10, 11, 12, 16, 15, 14, 13, 17, 18, 19, 20)
Just another way to approach the problem using list comprehension (not the fastest probably). Wanted to share the logic, assuming that len(a) is divisible by 4:
a = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)
lst = [a[j:j+4] if i%2 == 0 else a[j:j+4][::-1] for i, j in
enumerate(range(0,len(a), 4))]
result = tuple([j for i in lst for j in i])
print (result)
Output
(1, 2, 3, 4, 8, 7, 6, 5, 9, 10, 11, 12, 16, 15, 14, 13, 17, 18, 19, 20)

How to populate a 2d array?

I have the following code that (nearly) populates a list of lists (I will call it a 2d array) in Python.
Instead of going up from 0-6 and repeating this 3 times, I want it to populate the array with numbers 0 - 20. Please see code below:
#matrix=[1,2,3,4,5,6,7],[8,9,10,11,12,13,14],[15,16,17,18,19,20,21]
#print(matrix[1][2])
rows=3
columns=7
for i in range(rows):
for j in range(columns):
matrix=[j]
i=i+1
print(matrix,end="")
The erroneous output is:
[0][1][2][3][4][5][6][0][1][2][3][4][5][6][0][1][2][3][4][5][6]
I want the output to be:
[1,2,3,4,5,6,7],[8,9,10,11,12,13,14],[15,16,17,18,19,20,21]
There are fancier ways, but this is the most straightforward:
>>> rows = 3
>>> columns = 7
>>> n = 1
>>> matrix = []
>>> for _ in range(rows):
... sub = []
... for _ in range(columns):
... sub.append(n)
... n += 1
... matrix.append(sub)
...
>>> matrix
[[1, 2, 3, 4, 5, 6, 7], [8, 9, 10, 11, 12, 13, 14], [15, 16, 17, 18, 19, 20, 21]]
And for good measure, a fancy way:
>>> import itertools
>>> counter = itertools.count(1)
>>> rows = 3
>>> columns = 7
>>> matrix = [[n for n, _ in zip(counter, range(columns))] for _ in range(rows)]
>>> matrix
[[1, 2, 3, 4, 5, 6, 7], [9, 10, 11, 12, 13, 14, 15], [17, 18, 19, 20, 21, 22, 23]]
>>>
Use list comprehension. You want 3 rows so the base of the list comprehension is: [for y in range(rows)]. You want to have incrementing numbers starting with a number divisible by columns but starting from 1 so: range(columns*y+1,...) and you want to have columns range (7) so range(columns*y+1,columns+(columns*y+1)) and then turn that into a list.
rows=3
columns=7
matrix=[list(range(columns*y+1,columns+(columns*y+1))) for y in range(rows)]
print(matrix)
#outputs: [[1, 2, 3, 4, 5, 6, 7], [8, 9, 10, 11, 12, 13, 14], [15, 16, 17, 18, 19, 20, 21]]

How to split a sorted list into sub lists when two neighboring value difference is larger than a threshold

input:
a sorted list, like this:[1,2,3,8,10,15,16,17,18,22,23,27,30,31]
a threshold, like this: max_diff = 2
expected output:
a list of sub lists; each sub list contains the values that the neighboring difference is smaller than max_diff, like this: [[1, 2, 3], [8, 10], [15, 16, 17, 18], [22, 23], [27], [30, 31]]
Here's how I did this, I am wondering if there is a better way to do this.
test_list = [1,2,3,8,10,15,16,17,18,22,23,27,30,31]
max_diff = 2
splited_list = []
temp_list = [test_list[0]]
for i in xrange(1,len(test_list)):
if test_list[i] - temp_list[-1] > max_diff:
splited_list.append(temp_list)
temp_list = [test_list[i]]
else:
temp_list.append(test_list[i])
if i == len(test_list) -1:
splited_list.append(temp_list)
print splited_list
You can use enumerate and zip function within a list comprehension to find the indices of the elements that value difference is larger than 2, then split your list based on index list :
>>> li =[1, 2, 3, 8, 10, 15, 16, 17, 18, 22, 23, 27, 30, 31]
>>> inds=[0]+[ind for ind,(i,j) in enumerate(zip(li,li[1:]),1) if j-i>2]+[len(li)+1]
>>> [li[i:j] for i,j in zip(inds,inds[1:])]
[[1, 2, 3], [8, 10], [15, 16, 17, 18], [22, 23], [27], [30, 31]]
>>> a = [1,2,3,8,10,15,16,17,18,22,23,27,30,31]
>>> b = a[1:] #offset by 1 position
>>> b
[2, 3, 8, 10, 15, 16, 17, 18, 22, 23, 27, 30, 31]
>>> c = [(i[1] - i[0]) for i in zip(a[:-1], b)]
>>> c #position diff
[1, 1, 5, 2, 5, 1, 1, 1, 4, 1, 4, 3, 1]
>>> d = [i[0] for i in enumerate(c) if i[1] > 2]
>>> d #split position
[2, 4, 8, 10, 11]
>>> e = [-1]+d+[len(a)]
>>> e #add start end to split position
[-1, 2, 4, 8, 10, 11, 14]
>>> [a[l[0]+1: l[1]+1] for l in zip(e, e[1:])]
[[1, 2, 3], [8, 10], [15, 16, 17, 18], [22, 23], [27], [30, 31]]
#split result
Rearranging your lines leads to a more compact form:
test_list = [1,2,3,8,10,15,16,17,18,22,23,27,30,31]
max_diff = 2
splited_list = []
prev_element = float('-inf')
for element in test_list:
if element - prev_element > max_diff:
splited_list.append([])
splited_list[-1].append(element)
prev_element = element
print splited_list
Works on all iterables
def split_by_threshold(seq, max_diff=2):
it = iter(seq)
last = next(it)
part = [last]
for curr in it:
if curr - last > max_diff:
yield part
part = []
part.append(curr)
last = curr
yield part
l = [1,2,3,8,10,15,16,17,18,22,23,27,30,31]
print(list(split_by_threshold(l)))

Categories

Resources