I wish to split a list into same-sized chunks using a "sliding window", but instead of truncating the list at the ends, I want to wrap around so that the final chunk can be spread across the beginning and end of the list.
For example, given a list:
l = [1, 2, 3, 4, 5, 6]
I wish to generate chunks of size n=3 as follows:
[1, 2, 3], [4, 5, 6]
[2, 3, 4], [5, 6, 1]
[3, 4, 5], [6, 1, 2]
Or the same list with chunks of size n=2 should be split as follows:
[1, 2], [3, 4], [5, 6]
[2, 3], [4, 5], [6, 1]
The list may not be divided evenly into n sublists (e.g. if the original list has length 7 and n=3 - or any value other than 7 or 1). The rounded value len(l) / n can be used to determine the split size, as in the usual case.
This post is related, although it does not wrap around as I need. I have tried but not managed anything useful. Any suggestions would be most welcome!
You can use itertools.islice over a wrap-around iterator generated from itertools.cycle:
from itertools import cycle, islice
def rolling_chunks(l, n):
return ([list(islice(cycle(l), i + j, i + j + n)) for j in range(0, len(l), n)] for i in range(n))
so that list(rolling_chunks(l, 3)) returns:
[[[1, 2, 3], [4, 5, 6]], [[2, 3, 4], [5, 6, 1]], [[3, 4, 5], [6, 1, 2]]]
and that list(rolling_chunks(l, 2)) returns:
[[[1, 2], [3, 4], [5, 6]], [[2, 3], [4, 5], [6, 1]]]
Related
I'm trying to make a program that gets the "Kaprekar's constant" for base 5 numbers (numbers made from 0 to 4). Part of the process consists saving the numbers I'm getting in a list and repeat the Kaprekar's process, the result is compared with the saved numbers, if it's not in the list, add it and repeat...
The function I made for this:
def constantK(num):
before=[]
before.append(num)
after=kaprekar(num)
i=0
while(after not in before):
if i<5:
print(before,'--',after)
i += 1
before.append(after)
after=kaprekar(after)
return [after, len(before)]
The i and print are just for checking what's happening the first 5 times. This is what I get when calling constantK(base(39,5)):
[[4, 2, 1]] -- [2, 4, 2]
[[4, 2, 1], [4, 2, 2]] -- [1, 4, 3]
[[4, 2, 1], [4, 2, 2], [4, 3, 1]] -- [2, 4, 2]
[[4, 2, 1], [4, 2, 2], [4, 3, 1], [4, 2, 2]] -- [1, 4, 3]
[[4, 2, 1], [4, 2, 2], [4, 3, 1], [4, 2, 2], [4, 3, 1]] -- [2, 4, 2]
The base(a,b) function just returns a list of the digits for a written in base b.
As you can see, the value compared is not the same that the one is appended in before. I've checking for a while and have no idea why is this happening. I'd be glad with some help 🙂
I wanted to create a domino game. I'm in the beginning of my journey to become a python dev.
I have made enough progress but I'm wondering if i could refactor my unique set generator function more elegant - pythonic and shorter.
This is my function and i think it is working as it should be. All the other functions in the program are depended on this.
The main job of the function is creating a list of unique set of two random numbers (0-6(including)) range and all of those lists are inside a list.
For ex. [1,2] and [2,1] are the same and should appear only once in the final array.
from random import randrange
length = 28
def unique_set_generator(set_size):
unique_set = set()
main_set = []
while len(unique_set) != set_size:
x, y = randrange(7), randrange(7)
if (x, y) not in unique_set and (y, x) not in unique_set:
unique_set.add((x, y))
set_to_list = list(unique_set)
for i in range(set_size):
main_set.append(list(set_to_list[i]))
return main_set
print(unique_set_generator(length))
Outcome:
[[4, 3], [5, 4], [2, 2], [1, 0], [1, 3], [6, 5], [4, 2], [3, 3], [5, 0], [3, 6], [5, 3], [1, 2], [0, 4], [1, 5], [6, 1], [6, 4], [3, 2], [5, 2], [4, 4], [5, 5], [0, 0], [1, 1], [0, 3], [2, 0], [1, 4], [2, 6], [6, 0], [6, 6]]
Use the tools Python provides:
import random
dominos = [(i,j) for i in range(7) for j in range(i,7)]
print(dominos)
random.shuffle(dominos)
print(dominos)
I'm working with lists and I came up with a question. So basically, I have a 3D list in which I'm trying that after a for loop I maintain the second and penultimate element of the inner list, my code does the work, but it changes from a 3D list to a 2D list and I don't want that (this is just an example, mylist can have more elements) here is my code
mylist = [[[0, 4, 3, 5, 1], [0, 2, 1], [0, 2, 3, 1], [0, 3, 5, 1], [0, 2, 5, 3, 1]],
[[0, 4, 1], [0, 2, 1], [0, 4, 3, 1], [0, 4, 5, 1], [0, 4, 3, 1]]]
aux = []
for i in mylist:
for j in i :
if len(j) >= 4:
aux.append(j[1:-1])
print(aux)
# aux= [[4, 3, 5], [2, 3], [3, 5], [2, 5, 3], [4, 3], [4, 5], [4, 3]]
I got almost what I need, but I was expecting this output
aux = [[[4, 3, 5], [2, 3], [3, 5], [2, 5, 3]], [[4, 3], [4, 5], [4, 3]]] #Mantains the 3D dimension
I'm working on my list comprehension, but I'm not quite sure how to do this, this is what I try
aux = [[j[1:-1] if len(j) >= 4 for j in i] for i in mylist]
#But I get a syntax error
I don't know if there is a easier way to do this (must be, but I'm the guy who complicate things) maybe a a much easier list comprehension that I'm not seeing, so any help will be appreciated, thank you!
You got it right, only you have to move the if statement to after for in list comprehension:
aux = [[j[1:-1] for j in i if len(j)>=4] for i in mylist]
output:
[[[4, 3, 5], [2, 3], [3, 5], [2, 5, 3]], [[4, 3], [4, 5], [4, 3]]]
You were really close!
This should work. Look it over and see the logic involved
aux = [[j[1:-1] for j in i if len(j) >= 4] for i in mylist]
I have the list
Input:
L = [[1, 2, 3], [2, 3, 4], [5, 6, 7], [2, 3, 4], [2, 3, 5], [1, 2, 3], [1, 2, 3]]
Output:
L= [[5, 6, 7], [ 2, 3, 5]]
I want to check if L[i]== L[j], then I will remove L[j] from the list .
Can you help me?
This is my code:
for i in range(0,len(L) - 1):
for j in range(1,len(L) - 1):
if (L[i] == L[j]):
L.remove(L[j])
print(L)
But it gives an error:
if (L[i] == L[j]):
IndexError: list index out of range
Once you remove an element of L, the shape of L changes. This is why you are getting the index out of range error: you are still iterating over the original length of L, but once you start removing elements from L it becomes shorter than that.
You can get around this by creating a new list with count:
L2 = [sublist for sublist in L if L.count(sublist) == 1]
print(L2)
>>> [[5, 6, 7], [2, 3, 5]]
Note: your current logic, even if it adapted to the changing length of L, would not return your desired output. It would still retain the first 'copy' of all duplicate elements, as Richard Rublev's answer below produces.
If this is too slow (O(n2)), here is an O(n) solution using Counter:
from collections import Counter
# Converting elements to hashable type
L = [tuple(sublist) for sublist in L]
cnt = Counter(L)
# Grabbing non-duplicated items
L2 = [k for k, v in cnt.items() if v == 1]
# Converting elements back to lists
L2 = [list(sublist) for sublist in L2]
print(L2)
>>> [[5, 6, 7], [2, 3, 5]]
Try this
testdata = [[1, 2, 3], [2, 3, 4], [5, 6, 7], [2, 3, 4], [2, 3, 5], [1, 2, 3], [1, 2, 3]]
unique = [list(x) for x in set(tuple(x) for x in testdata)]
Result
[[2, 3, 5], [2, 3, 4], [5, 6, 7], [1, 2, 3]]
My task is to calculate the k-permutations from the updated List by new element
without recalculating the k-permutations already gotten from the previous state of the list. Example:
liste = [1, 2, 3]
3-permutations are:
[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]
The updated list:
liste = [1, 2, 3, 4]
I would like to obtain directly 3-permutations[1, 2, 3, 4]-3-permutations[1, 2, 3]
without recalculating 3-permutations[1, 2, 3]
Calculate directly the new permutations:
[1, 2, 4], [1, 3, 4], [1, 4, 2], [1, 4, 3], [2, 1, 4], [2, 3, 4], [2, 4, 1],
[2, 4, 3], [3, 1, 4], [3, 2, 4], [3, 4, 1], [3, 4, 2], [4, 1, 2], [4, 1, 3],
[4, 2, 1], [4, 2, 3], [4, 3, 1], [4, 3, 2]
Thanks
Computing first the cartesian product {0,1,2,3}x{0,1,2}x{0,1} and taking the nth element of list (1,2,3,4).
r=[]
for prd in itertools.product([[0,1,2,3],[0,1,2],[0,1]]):
l=[1,2,3,4]
r0=[]
for i in prd:
r0 += l[i]
del l[i]
r += r0
EDIT: original answer gives the 3-permutations of [1,2,3,4]
following command answers specifically to question, see how it can be generalized
[list(j) for i in itertools.combinations([1,2,3],2) for j in itertools.permutations(list(i)+[4])]
next case, maybe one of ?
[list(j) for i in itertools.combinations([1,2,3],2) for j in itertools.permutations(list(i)+[4,5])]
[list(j) for i in itertools.combinations([1,2,3,4],3) for j in itertools.permutations(list(i)+[4,5])]
try saving the existing permutations to a list, then do:
if newPermutation not in listOfExistingPermutations:
listOfExistingPermutations.append(newPermutation)
or something along those lines