# Removing from a sublist, inserting into another one

From a list like

test = {{1, 3}, {2,7, 8}, {5,6}};


I would like to randomly select k elements, lift them out of their current sublist and place them into a different random sublist and sort the sublist.

Desired output should look like:

 RandomSwap[test]
{{1}, {2,7}, {3,5,6,8}};

RandomSwap[test]
{{1,7}, {2,6}, {3,5,8}};


I can get the indexes of the elements I need to swap by doing (if I'm looking for 2 elements in this tiny example)

 k =2
ListIndexes = RandomSample[Range[Length[test]], k]


Then select a random number of entries in each sub list

 ElementsIndexes =  Flatten[RandomSample[#, 1] & /@ Range[Map[Length, child[[MutationIndexes]]]]]


But I don't know how to perform the swaps in an efficient/vectorized way.

This selects positions from the indices of the ragged array, Deletes these positions, and then Inserts the deleted values into new randomly selected sublist (excluding the source sublist). The Sort can be included in the function if needed.

randomSwap[list_, k_] :=
With[{pos =
RandomSample[Flatten@MapIndexed[#2 -> #1 &, list, {2}], k]},
Fold[
Insert[#1, Last@#2, First@#2] &,
Delete[list, Keys@pos],
MapAt[
{RandomChoice[DeleteCases[First@#]@Range@Length@list], -1} &,
{All, 1}]@pos
]
]


With test as in OP for 5 examples

SeedRandom
Sort /@ randomSwap[test, #] & /@ Range@5 // Column

{{1,3,7},{2,8},{5,6}}
{{1,3},{7},{2,5,6,8}}
{{1,2},{3,6,7,8},{5}}
{{1,7},{},{2,3,5,6,8}}
{{1,5},{6,8},{2,3,7}}


Hope this helps.

Another approach:

RandomSwap[list_, k_] := Module[{range, pos, move},
range = Range[Length[list]];
pos = Join @@ MapThread[ConstantArray, {range, Length /@ list}];
move = RandomSample[PadRight[RandomInteger[{1, Length[list] - 1}, k], Length[pos]]];
pos = Mod[pos + move, Length[list], 1];
TakeList[(Join @@ list)[[Ordering[Transpose[{pos, Join @@ list}]]]],
Lookup[Counts[pos], range, {}]]]

RandomSwap[test, 2]

{{1, 3, 5, 7}, {2, 8}, {6}}