Move element inside a list
data = {a, b, c, d, e, f};
Permute[data, {3, 1, 2}]
or
Permute[data, Cycles[{{1, 3, 2}}]]
Both give
{b, c, a, d, e, f}
Edit
It occurred to me that it would be good to be able to move an element to a lower position in the list as well as a higher one. Together the following two functions give both capabilities.
Upward movement -- move an element at position m
to position n
, where m < n
:
moveElementUp[data_List, m_Integer /; m > 0, n__Integer /; n > 0] /; m < n :=
Permute[data, Join[Range[m - 1], {n}, Range[m, n - 1]]]
moveElementUp[data, 1, 3]
{b, c, a, d, e, f}
moveElementUp[data, 2, 5]
{a, c, d, e, b, f}
moveElementUp[data, 1, 6]
{b, c, d, e, f, a}
Downward movement -- move an element at position m
to position n
, where m > n
:
moveElementDown[data_List, m_Integer /; m > 0, n__Integer /; n > 0] /; m > n :=
Permute[data, Join[Range[n - 1], 1 + Range[n, m - 1], {n}]]
moveElementDown[data, 3, 1]
{c, a, b, d, e, f}
moveElementDown[data, 5, 3]
{a, b, e, c, d, f}
moveElementDown[data, 6, 1]
{f, a, b, c, d, e}
Note
Although I found it interesting to attack this problem with permutations, I suspect there is a better solution.
Probably not the most elegant way but...
swap[list_, from_, to_] :=
Module[{ele = list[[from]], modlist = list},
modlist[[from]] = Sequence[]; modlist = Insert[modlist, ele, to];
modlist]
swap[list, 1, 3]
{b, c, a, d, e, f}
If you always want the moving element in front of d
...
swap[list, 1, FirstPosition[list, d] - 1]
Note, in 10.2 you can use Nothing
instead of Sequence[]
.
Or, if you insist on using patterns...
from = 1;
to = 3;
list /. {a___, list[[from]], b___, list[[to + 1]], c___} :> {a, b,
list[[from]], list[[to + 1]], c}
The following answer is effectively equivalent to m_goldberg's answer, except that the distinction between the two directions of movement has been eliminated:
moveElement[l_List, m_Integer?Positive, n_Integer?Positive] :=
Module[{idx},
idx = Range @@ Sort[{m, n}];
ReplacePart[l, Thread[idx -> l[[RotateLeft[idx, Sign[n - m]]]]]]]
Both moveElementUp[]
and moveElementDown[]
in his answer can be replaced with this unified function.