问题
I am trying to do shuffling of pairs in an array of images, and it is a little bit tricky for me.
Example: I have 20 sequences of images, each containing 1000 frames .. they are saved in an array .. so let's assume, the array looks like that
[[1_1],[1_2],[1_3],[1_4],[1_5],[1_6],[2_1],[2_2],[2_3],[2_4],[2_5],[2_6],[3_1],[3_2],[3_3],[3_4],[3_5],[3_6]]
And so on, this is just a minimal example of 3 sequences, each having 6 frames .. but what I want to achieve in the end, of shuffling of sequential frames, so something like that
[[1_4],[1_5],[2_3],[2_4],[3_5],[3_6],[1_3],[1_4],[1_1],[1_2],[3_2],[3_3],[1_2],[1_3],[3_3],[3_4],[2_1],[2_2] ....]
So something like this simply .. So I want to produce a shuffle, but instead of single elements, it will be each element along with the follwoing one, i.e. I want to shuffle pairs.
Is there a way to do so ?
回答1:
I am working on a cleaner nested list (mistrusting the [1_1]):
L = [['1_1'],['1_2'],['1_3'],['1_4'],['1_5'],['1_6'],['2_1'],['2_2'],['2_3'],['2_4'],['2_5'],['2_6'],['3_1'],['3_2'],['3_3'],['3_4'],['3_5'],['3_6']]
Then I create a nested list, i.e. a list of pairs, with a comprehension:
S=[[L[z*2+y] for y in range(2)] for z in range(len(L)//2)] # version 1
S=[[L[z+y] for y in range(2)] for z in range(len(L)-1)] # version 2
S
Note that there are length/2 non-overlapping pairs, but N-1 overlapping pairs (one pair for each entry, except the last).
Note that in all outputs below I have manually added newlines for readability and clarity purposes.
Output at this point is:
Version 1, non-overlapping pairs:
[[['1_1'], ['1_2']],
[['1_3'], ['1_4']],
[['1_5'], ['1_6']],
[['2_1'], ['2_2']],
[['2_3'], ['2_4']],
[['2_5'], ['2_6']],
[['3_1'], ['3_2']],
[['3_3'], ['3_4']],
[['3_5'], ['3_6']]]
Version 2, overlapping pairs:
[[['1_1'], ['1_2']],
[['1_2'], ['1_3']],
[['1_3'], ['1_4']],
[['1_4'], ['1_5']],
[['1_5'], ['1_6']],
[['1_6'], ['2_1']],
[['2_1'], ['2_2']],
[['2_2'], ['2_3']],
[['2_3'], ['2_4']],
[['2_4'], ['2_5']],
[['2_5'], ['2_6']],
[['2_6'], ['3_1']],
[['3_1'], ['3_2']],
[['3_2'], ['3_3']],
[['3_3'], ['3_4']],
[['3_4'], ['3_5']],
[['3_5'], ['3_6']]]
Then shuffle S, which will only shuffle the pairs within S, not within the pairs, that is the point of making the list of pairs first.
import random
random.shuffle(S)
S
Output at this point, still nested of course:
Non-overlapping random pairs:
[[['3_3'], ['3_4']],
[['3_1'], ['3_2']],
[['2_3'], ['2_4']],
[['3_5'], ['3_6']],
[['1_1'], ['1_2']],
[['1_3'], ['1_4']],
[['2_1'], ['2_2']],
[['1_5'], ['1_6']],
[['2_5'], ['2_6']]]
Output overlapping random pairs:
[[['1_2'], ['1_3']],
[['2_1'], ['2_2']],
[['2_4'], ['2_5']],
[['2_2'], ['2_3']],
[['1_3'], ['1_4']],
[['3_4'], ['3_5']],
[['3_3'], ['3_4']],
[['3_2'], ['3_3']],
[['1_6'], ['2_1']],
[['2_5'], ['2_6']],
[['2_6'], ['3_1']],
[['1_4'], ['1_5']],
[['1_1'], ['1_2']],
[['2_3'], ['2_4']],
[['1_5'], ['1_6']],
[['3_1'], ['3_2']],
[['3_5'], ['3_6']]]
Maybe you can use that for the rest of the project.
If not dissolve the pairs
L2=[]
for x in S:
for y in x:
L2.append(y)
print(L2)
Output dissolved non-overlapping pairs:
[['3_3'], ['3_4'], ['3_1'], ['3_2'], ['2_3'], ['2_4'],
['3_5'], ['3_6'], ['1_1'], ['1_2'], ['1_3'], ['1_4'],
['2_1'], ['2_2'], ['1_5'], ['1_6'], ['2_5'], ['2_6']]
Output dissolved overlapping pairs:
[['1_2'], ['1_3'], ['2_1'], ['2_2'], ['2_4'], ['2_5'],
['2_2'], ['2_3'], ['1_3'], ['1_4'], ['3_4'], ['3_5'],
['3_3'], ['3_4'], ['3_2'], ['3_3'], ['1_6'], ['2_1'],
['2_5'], ['2_6'], ['2_6'], ['3_1'], ['1_4'], ['1_5'],
['1_1'], ['1_2'], ['2_3'], ['2_4'], ['1_5'], ['1_6'],
['3_1'], ['3_2'], ['3_5'], ['3_6']]
回答2:
We will need a few imports to simplify things:
from functools import reduce
from itertools import groupby
import operator
import random
Assuming you have a list like:
ar = [['1_1'],['1_2'],['1_3'],['1_4'],['1_5'],['1_6'],['2_1'],['2_2'],['2_3'],['2_4'],['2_5'],['2_6'],['3_1'],['3_2'],['3_3'],['3_4'],['3_5'],['3_6']]
We can first group them up by image so that we only generate valid pairs:
groupedbyimage = [list(g[1]) for g in groupby(ar, lambda x: x[0][0])]
The above lambda would have to be something else in your case in order to generate find the correct groups when not just comparing the first letter in the string in the nested lists.
Next we can zip the image lists with themselves shifted by one:
groupedandpaired = [list(zip(x, x[1:])) for x in groupedbyimage]
We can now flatten the groupedandpaired list into a pairlist:
pairlist = reduce(operator.concat, groupedandpaired)
Now we can just shuffle the list of pairs and then flatten it again to get the desired result:
random.shuffle(pairlist)
result = list(reduce(operator.concat, pairlist))
And printing the result in the REPL we see something like:
>>> result
[['1_5'], ['1_6'], ['2_1'], ['2_2'], ['1_1'], ['1_2'], ['3_2'],
['3_3'], ['2_2'], ['2_3'], ['3_5'], ['3_6'], ['3_1'], ['3_2'],
['1_3'], ['1_4'], ['1_4'], ['1_5'], ['3_4'], ['3_5'], ['3_3'],
['3_4'], ['2_5'], ['2_6'], ['2_3'], ['2_4'], ['1_2'], ['1_3'],
['2_4'], ['2_5']]
来源:https://stackoverflow.com/questions/51980490/how-to-shuffle-array-of-implicit-pairs