I have a problem with understanding one process which is splitting array on smaller arrays. I'm posting the two lines below and I would appreciate if you could explain to me what certain part does. Thank you in advance :)
my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
# How many elements each
# list should have
n = 4
final = [my_list[i * n:(i + 1) * n] for i in range((len(my_list) + n - 1) // n )]
# Almost the same code with some changes:
def split_list(alist, wanted_parts=1):
length = len(alist)
return [ alist[i*length // wanted_parts: (i+1)*length // wanted_parts]
for i in range(wanted_parts) ]
A = [0,1,2,3,4,5,6,7,8,9]
what is your problem?
you have the initial list
my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
for example, you want to split it on 3 parts. So you call function
split_list(my_list, wanted_parts =3)
inside function, you will have:
length = len(alist) # it will be 9
then you have this:
for i in range(wanted_parts) # range(3), so it would be i = [0,1,2]
then you have:
alias[xxxx:yyyy] # where xxxx - start point of slice and yyyy - end point of slice, and you have it 3 times and pass there i = (0,1,2)
now lets check xxxx. in your case it is:
i*length // wanted_parts # i=0..2, length = 9, wanted_parts = 3, so all of this = 0, 3, 6
now lets check yyyy. in your case it is:
(i+1)*length // wanted_parts. # i = 0..2, (i+1) = 1..3, length = 9, wanted_parts = 3, so all of this = 3, 6, 9
so totaly you will have:
[0:3], [3:6], [6:9] # - and it will be 3 parts of your list
Related
I've been trying to accomplish a simple linear sort that will, in this case, make a swap at every index except for when it reaches the end. Kindly help. (the while loop might be unnecessary at this point)
array = list(range(9, -1, -1))
has_flipped = True
while has_flipped:
for num in array:
if array.index(num) == (len(array) - 1):
continue
if num > array[array.index(num) + 1]:
container = array[array.index(num) + 1]
array[array.index(num) + 1] = num
num = container
has_flipped = False
has_flipped = not has_flipped
I expect a list with the numbers 0 through 9 but I instead get 9, 9, 7, 7, 5, 5, 3, 3, 1, 1.
You do not swap rightly. You never assign to array locations in right manner. As the other answerer explains...
num = container
...does not assign to an array location.
Moreover, the while loop is not required. Here is a more compact way of doing the same:
array = list(range(9, -1, -1))
ln = len(array)
for num in array:
if num > array[ln-1]:
container = array[ln-1]
array[ln-1] = num
array[array.index(num)] = container
ln -= 1
print(array)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
I am trying to write a for loop such that it only contains numbers between 1 and 7 (both inclusive) and the numbers get stored in a list.
The length of the list should be 8629.
This is the code which i try to run. I get this error: SyntaxError: invalid syntax
random_list = []
for i in range(0,8628):
x = i % 7
random_list[i].append(x+1)
while i == i + 1
print(random_list)
if your requirement is :
The length of the list should be 8629 and write a for loop such that it only contains numbers between 1 and 7. shouldn't it be like this?
from random import *
random_list = []
while len(random_list) < 5:
random_list.append(randint(1, 7))
print(random_list)
random_list = [i % 7 + 1 for i in range(8628)]
print(random_list)
The list will be :[1,2,3,4,5,6,7,...........]
This will give random integers in the range you specified:
Code
import random
random_list = [random.randint(1, 7) for _ in range(8629)]
Test
random_list[:10]
# [3, 4, 4, 5, 3, 1, 3, 7, 7, 6]
min(random_list), max(random_list)
# (1, 7)
len(random_list)
# 8629
For a cycle of consecutive numbers, try itertools:
Code
import itertools as it
cycled_list = list(it.islice(it.cycle(range(1, 8)), 8629))
Test
cycled_list[:10]
# [1, 2, 3, 4, 5, 6, 7, 1, 2, 3]
min(cycled_list), max(cycled_list)
# (1, 7)
len(cycled_list)
# 8629
See #Ming Chu's post for list compression variant.
I am trying to randomly replace 20% of a list in python:
ls = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
ls = [1, 2, NULL, 4, 5, 6, NULL, 8, 9, 10]
ls = [1, 2, 82, 4, 5, 6, 28, 8, 9, 10]
so far
while n <= len(ls)/5
ls[randint(0, 9)]=randint(1, 100)
n += 1
but it has a fairly large chance of removing and replacing the same entry multiple times in one run.
Assuming ls could be anything, I would recommend generating a list of indices, corresponding to ls. Then, you may use random.sample to pick up 20% of those indices, and then alter those only.
From the docs:
Return a k length list of unique elements chosen from the population
sequence. Used for random sampling without replacement.
In [816]: for _i in random.sample(range(len(ls)), len(ls) // 5):
...: ls[_i] = random.randint(1, 100)
...:
In [817]: ls
Out[817]: [1, 92, 3, 4, 5, 6, 7, 8, 75, 10]
Unless your lists are very large, you can select a sample from the indexes. For example:
for idx in random.sample(range(len(ls)), len(ls)/5):
ls[idx]=random.randint(1, 100)
You can shuffle a range of indexes and then take first n indexes that has to be changed.
from random import shuffle
x = [[i] for i in range(10)]
shuffle(x)
#change x[0], x[1], .. x[n-1]
If you want to eliminate the chance of the same index getting replaced the second time, you can store the result of randint(0, 9) in a variable. In the next iterations, use an if condition to check if randint() returned the same index as the previous iteration. If yes, then continue and do not increment n.
Alternatively, you can use random.sample() to pick up a given number of samples - 20% of the list size in your case.
Best option would be to pick 20% worth of indexes and then replace them in the list. Something like:
from random import randint
twenty_percent = round(len(ls) / 5)
for i in range(twenty_percent):
ls[randint(0, len(ls) - 1)] = randint(1, 100)
This answer takes INDEX into account, so it won't replace the same value twice.
ls = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
n = len(ls)
x = round(n/5)
for i in range(x):
index = randint(0, n)
del ls[index]
ls.insert(index, randint(0, 100))
print(ls)
Works for me. See if it does the job.
I'm working through this Kata and although I've looked through the solutions none are quite similar enough to mine to answer my question.
Problem Text: The number 89 is the first integer with more than one digit that fulfills the property partially introduced in the title of this kata. What's the use of saying "Eureka"? Because this sum gives the same number.
In effect: 89 = 8^1 + 9^2
The next number in having this property is 135.
See this property again: 135 = 1^1 + 3^2 + 5^3
We need a function to collect these numbers, that may receive two integers a, b that defines the range [a, b] (inclusive) and outputs a list of the sorted numbers in the range that fulfills the property described above.
def sum_dig_pow(a, b): # range(a, b + 1) will be studied by the function
# your code here
lst = []
n = 1
tot = 0
for i in range(a,b):
if i > 9:
spl = str(i).split()
for item in spl:
tot += int(item) ** n
n += 1
if tot == i:
lst.append(i)
else:
lst.append(i)
return lst
Tests are returning "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] should equal [1, 2, 3, 4, 5, 6, 7, 8, 9, 89]".
I cannot figure out why it's passing 10 and not appending 89. I'm sure there's a more efficient way to do this as well but I'm still learning so want to be working in basics of loops, conditionals,etc.
This line is incorrect:
spl = str(i).split()
The split method will split a string on spaces by default and return a list. So passing i=10 gives back spl = ['10'], a list with one element. Instead, just iterate over each of the digits in the string.
for item in str(i):
...
Follow up: you can shorten your code by using enumerate to count the index of each digit.
def sum_dig_pow(a,b):
return [sum(int(y)**(i+1) for i,y in enumerate(str(x))) for x in range(a,b)]
Rather than spending a lot of time converting things from numbers to strings and back, try using arithmetic. To iterate over the digits of a number n, take n modulo ten (to get the least-significant digit) and then divide by ten (to peel off that least-significant digit). For example, the digits of 123 (in reverse order) are [(123 % 10), (12 % 10), (1 % 10)]
Thinking of it in terms of functions, first get the digits:
def digits_of_n(n):
result = []
while n > 0:
result.append(n % 10)
n = n / 10 # in python 3, use 3 // 10 for integer division
return reversed(result) # reverse list to preserve original order
then get the sum of the powers:
def sum_of_ith_powers(numbers):
result = 0
for i, n in enumerate(numbers): # the digits are ordered most-significant to least, as we would expect
result += n ** 1
return result
now you can just call sum_of_ith_powers(digits_of_n(n)) and you have an answer. If you like, you can give that operation a name:
def sum_of_digit_powers(n):
return sum_of_ith_powers(digits_of_n(n))
and you can then name the function that solves the kata:
def solve_kata(a, b):
return [sum_of_digit_powers(n) for n in range (a, b)]
You can use a generator, sum and enumerate in order to simplify your code like this example:
def sum_dig_pow(a,b):
for k in range(a,b+1):
if k > 9:
number_sum = sum(int(j)**i for i,j in enumerate(str(k), 1))
if k is number_sum:
yield k
else:
yield k
print(list(sum_dig_pow(1,10)))
print(list(sum_dig_pow(1,90)))
print(list(sum_dig_pow(1,10000)))
print(list(sum_dig_pow(10,1000)))
print(list(sum_dig_pow(1,900000)))
Output:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 89]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 89, 135, 175]
[89, 135, 175]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 89, 135, 175]
li = []
def sum_dig_pow(a, b):
for i in range(a, b+1):
sum1 = 0
for ind, val in enumerate(str(i), 1):
sum1 += pow(int(val), int(ind))
if i == sum1:
li.append(i)
return li
print(sum_dig_pow(1, 11))
I am trying to do the following..
I have a list of n elements. I want to split this list into 32 separate lists which contain more and more elements as we go towards the end of the original list. For example from:
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
I want to get something like this:
b = [[1],[2,3],[4,5,6,7],[8,9,10,11,12]]
I've done the following for a list containing 1024 elements:
for i in range (0, 32):
c = a[i**2:(i+1)**2]
b.append(c)
But I am stupidly struggling to find a reliable way to do it for other numbers like 256, 512, 2048 or for another number of lists instead of 32.
Use an iterator, a for loop with enumerate and itertools.islice:
import itertools
def logsplit(lst):
iterator = iter(lst)
for n, e in enumerate(iterator):
yield itertools.chain([e], itertools.islice(iterator, n))
Works with any number of elements. Example:
for r in logsplit(range(50)):
print(list(r))
Output:
[0]
[1, 2]
[3, 4, 5]
[6, 7, 8, 9]
... some more ...
[36, 37, 38, 39, 40, 41, 42, 43, 44]
[45, 46, 47, 48, 49]
In fact, this is very similar to this problem, except it's using enumerate to get variable chunk sizes.
This is incredibly messy, but gets the job done. Note that you're going to get some empty bins at the beginning if you're logarithmically slicing the list. Your examples give arithmetic index sequences.
from math import log, exp
def split_list(_list, divs):
n = float(len(_list))
log_n = log(n)
indices = [0] + [int(exp(log_n*i/divs)) for i in range(divs)]
unfiltered = [_list[indices[i]:indices[i+1]] for i in range(divs)] + [_list[indices[i+1]:]]
filtered = [sublist for sublist in unfiltered if sublist]
return [[] for _ in range(divs- len(filtered))] + filtered
print split_list(range(1024), 32)
Edit: After looking at the comments, here's an example that may fit what you want:
def split_list(_list):
copy, output = _list[:], []
length = 1
while copy:
output.append([])
for _ in range(length):
if len(copy) > 0:
output[-1].append(copy.pop(0))
length *= 2
return output
print split_list(range(15))
# [[0], [1, 2], [3, 4, 5, 6], [7, 8, 9, 10, 11, 12, 13, 14]]
Note that this code is not efficient, but it can be used as a template for writing a better algorithm.
Something like this should solve the problem.
for i in range (0, int(np.sqrt(2*len(a)))):
c = a[i**2:min( (i+1)**2, len(a) )]
b.append(c)
Not very pythonic but does what you want.
def splitList(a, n, inc):
"""
a list to split
n number of sublist
inc ideal difference between the number of elements in two successive sublists
"""
zr = len(a) # remaining number of elements to split into sublists
st = 0 # starting index in the full list of the next sublist
nr = n # remaining number of sublist to construct
nc = 1 # number of elements in the next sublist
#
b=[]
while (zr/nr >= nc and nr>1):
b.append( a[st:st+nc] )
st, zr, nr, nc = st+nc, zr-nc, nr-1, nc+inc
#
nc = int(zr/nr)
for i in range(nr-1):
b.append( a[st:st+nc] )
st = st+nc
#
b.append( a[st:max(st+nc,len(a))] )
return b
# Example of call
# b = splitList(a, 32, 2)
# to split a into 32 sublist, where each list ideally has 2 more element
# than the previous
There's always this.
>>> def log_list(l):
if len(l) == 0:
return [] #If the list is empty, return an empty list
new_l = [] #Initialise new list
new_l.append([l[0]]) #Add first iteration to new list inside of an array
for i in l[1:]: #For each other iteration,
if len(new_l) == len(new_l[-1]):
new_l.append([i]) #Create new array if previous is full
else:
new_l[-1].append(i) #If previous not full, add to it
return new_l
>>> log_list([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
[[1], [2, 3], [4, 5, 6], [7, 8, 9, 10]]