4
$\begingroup$

If I have the following code:

randomstring = "D"
lis1 = {{{"J","D","W","L"},{"Q","R","T","D"},{"O","P","D","W"},{"D","Z","L","M"}}}

How could I rearrange the sublists here so that each sublist has string "D"moved to the front of it (if "D" starts in the front then nothing has to be done to that sublist)? Since moving "D" means the positions of some of the other strings change, I'd be okay with just swapping whatever starts in position 1 in each sublist for whatever position the "D" is in, for example:

{{{"D","J","W","L"}...}}

So the two strings "D" and "J"had switched places. Overall though it doesn't matter what positions the remaining three strings are in, I'm just trying to rearrange the sublists so that each one starts with the string "D".

$\endgroup$
1
  • 1
    $\begingroup$ {Sort /@ lis1[[1]]} for your example... $\endgroup$ – ciao Aug 26 '20 at 17:43
4
$\begingroup$

Move D to the front, leaving the order of the rest unchanged:

lis1 /. {a___String, "D", b___String} :> {"D", a, b}

{{{"D", "J", "W", "L"}, {"D", "Q", "R", "T"}, {"D", "O", "P",
"W"}, {"D", "Z", "L", "M"}}}

Swap the first element and D:

lis1 /. {a_String, b___String, "D", c___String} :> {"D", b, a, c}

{{{"D", "J", "W", "L"}, {"D", "R", "T", "Q"}, {"D", "P", "O",
"W"}, {"D", "Z", "L", "M"}}}

If there is a D in every list or if every list should start with D regardless, this would suffice as well:

Map[Prepend["D"], DeleteCases[lis1, "D", {3}], {2}]

{{{"D", "J", "W", "L"}, {"D", "Q", "R", "T"}, {"D", "O", "P",
"W"}, {"D", "Z", "L", "M"}}}

And here's one just for fun:

MapThread[RotateLeft, {lis1, {Position[lis1, "D"][[All, -1]] - 1}}, 2]

{{{"D", "W", "L", "J"}, {"D", "Q", "R", "T"}, {"D", "W", "O",
"P"}, {"D", "Z", "L", "M"}}}

$\endgroup$
2
$\begingroup$
lis2 = {{{"J", "D", "W", "A"}, {"Q", "R", "T", "D"}, 
    {"O", "P", "D",  "W"}, {"D", "Z", "L", "M"}}};

We can also use SortBy or Sort to get the desired results:

If "it doesn't matter what positions the remaining three strings are in":

Map[SortBy[# != "D" &], lis2, {2}]
 {{{"D", "A", "J", "W"}, 
  {"D", "Q", "R", "T"}, 
  {"D", "O", "P", "W"}, 
  {"D", "L", "M", "Z"}}}

If the other elements are to be kept in original order,

Map[SortBy[{# != "D" &, False &}], lis2, {2}]
 {{{"D", "J", "W", "A"}, 
  {"D", "Q", "R", "T"}, 
  {"D", "O", "P", "W"},
  {"D", "Z", "L", "M"}}}

We can use Sort with a custom ordering function:

ord["D", _] = True;
ord[_, "D"] = False;
ord[a_, b_] := Order[a, b];

Map[Sort[#, ord] &, lis2, {2}]
  {{{"D", "A", "J", "W"}, 
  {"D", "Q", "R", "T"}, 
  {"D", "O", "P", "W"}, 
  {"D", "L", "M", "Z"}}}

Use the ord[a_,b_] = 0 to keep the original order of elements other than "D":

Map[Sort[#, ord] &, lis2, {2}]
 {{{"D", "J", "W", "A"}, 
 {"D", "Q", "R", "T"},
 {"D", "O", "P", "W"},
 {"D", "Z", "L", "M"}}}
$\endgroup$
2
$\begingroup$

If "it doesn't matter what positions the remaining three strings are in" and no repeated element in each sublist:

prep[x_] := DeleteDuplicates /@ (Prepend[#, "D"] & /@ First@x)
prep@lis1

{{"D", "J", "W", "L"}, {"D", "Q", "R", "T"}, {"D", "O", "P", "W"}, {"D", "Z", "L", "M"}}

Or

lis2 = First@lis1;
prep[x_] := DeleteDuplicates@Prepend[x, "D"]
prep /@ lis2
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.