13
$\begingroup$

I have nested list with sublists of varying lengths like this:

list={{a,b,c,d},{e,f},{g,h,i},{j},{k,l},{m,n,o}}

How can I join the 4th and 5th sublists based on their position to give me:

{{a,b,c,d},{e,f},{g,h,i},{j,k,l},{m,n,o}}

The closest I have managed to get is using:

FlattenAt[list, {{4}, {5}}]

But this gives:

{{a, b, c, d}, {e, f}, {g, h, i}, j, k, l, {m, n, o}}

Thanks in advance.

$\endgroup$
0

8 Answers 8

11
$\begingroup$

You could use SubsetMap (available from version 12.0), but since it requires you to return the same size you get, we could trick it by Hold and Nothing:

ReleaseHold @ SubsetMap[{Join @@ #, Hold @ Nothing} &, list, {4, 5}]

(* Out: {{a, b, c, d}, {e, f}, {g, h, i}, {j, k, l}, {m, n, o}} *)
$\endgroup$
1
  • $\begingroup$ This is great, works really well. Thanks! $\endgroup$
    – wmv
    Commented Apr 21, 2022 at 15:09
9
$\begingroup$

Another approach using Delete, Extract and Insert:

Insert[Delete[list, #], Join @@ Extract[list, #], 4] & @@ {{{4}, {5}}}
(*{{a, b, c, d}, {e, f}, {g, h, i}, {j, k, l}, {m, n, o}}*)
$\endgroup$
8
$\begingroup$
ClearAll[spliceParts]
spliceParts =  Module[{l = #, p = Flatten @ #2},
  l[[First @ p]] =Flatten @ l[[p]]; l[[Rest @ p]] = Nothing; l] &;

Examples:

list = {{a, b, c, d}, {e, f}, {g, h, i}, {j}, {k, l}, {m, n, o}};

spliceParts[list, {{4}, {5}}]
{{a, b, c, d}, {e, f}, {g, h, i}, {j, k, l}, {m, n, o}}
spliceParts[list, { {4}, {5}, {2}}]
{{a, b, c, d}, {g, h, i}, {j, k, l, e, f}, {m, n, o}} 
$\endgroup$
5
$\begingroup$

Another way of doing it, albeit not elegant

Join[list[[1 ;; 3]], {Join[list[[4]], list[[5]]]}, {list[[6]]}]

out

$\endgroup$
4
$\begingroup$

Maybe we can do the 10 ways again, why not?

Hence, one way of doing it

TakeList[Flatten[list], {4, 2, 3, 3, 3}]

out1

$\endgroup$
3
  • 1
    $\begingroup$ The ten ways team! :) $\endgroup$ Commented Apr 22, 2022 at 16:29
  • 1
    $\begingroup$ @E.Chan-López maybe we should have a banner next to questions with 10 or more answers :) Like level of awesomeness reached or something! $\endgroup$
    – bmf
    Commented Apr 22, 2022 at 16:30
  • $\begingroup$ That's an excellent idea, @bmf! $\endgroup$ Commented Apr 22, 2022 at 16:31
4
$\begingroup$

As ReplacePart "uses rules in the order given", ReplacePart may be used to Join sublists at the first position specified, and then remove all but the joined sublist:

ReplacePart[list, Flatten[{4:> Join[Sequence@@list[[{4,5}]]], Thread[{4,5}:> Nothing]}]]

{{a, b, c, d}, {e, f}, {g, h, i}, {j, k, l}, {m, n, o}}

As a 'pure' function:

ReplacePart[#1, Flatten[{#2[[1]]:> Join[Sequence@@#1[[##2]]], 
    Thread[##2:> Nothing]}]]&@@{list,{4,5}}

{{a, b, c, d}, {e, f}, {g, h, i}, {j, k, l}, {m, n, o}}


ReplacePart[#1, Flatten[{#2[[1]]:> Join[Sequence@@#1[[##2]]], 
    Thread[##2:> Nothing]}]]&@@{list,{5,4,1}

{{e, f}, {g, h, i}, {k, l, j, a, b, c, d}, {m, n, o}}

As a function:

f[lst_List,pos_List]:= ReplacePart[lst, Flatten[{pos[[1]]:> Join[Sequence@@lst[[pos]]], 
                         Thread[pos:> Nothing]}]]

Examples

f[list, {4,5}]

{{a, b, c, d}, {e, f}, {g, h, i}, {j, k, l}, {m, n, o}}

f[list, {6,1,3}]

{{e, f}, {j}, {k, l}, {m, n, o, a, b, c, d, g, h, i}}


list//f[#,Reverse@Range@Length@#]&//Catenate

{m, n, o, k, l, j, g, h, i, e, f, a, b, c, d}

where

list={{a, b, c, d}, {e, f}, {g, h, i},{j}, {k, l}, {m, n, o}};
$\endgroup$
3
$\begingroup$

A solution with ApplyTo

list = {{a, b, c, d}, {e, f}, {g, h, i}, {j}, {k, l}, {m, n, o}};

join = list;
join[[4 ;; 5]] //= Join @@ # &;
join

{{a, b, c, d}, {e, f}, {g, h, i}, {j, k, l}, {j, k, l}, {m, n, o}}

$\endgroup$
2
$\begingroup$
list = {{a, b, c, d}, {e, f}, {g, h, i}, {j}, {k, l}, {m, n, o}};

OP's idea to use FlattenAt works with SequenceReplace

SequenceReplace[x : {_?AtomQ ..} :> x] @ FlattenAt[list, {{4}, {5}}]

{{a, b, c, d}, {e, f}, {g, h, i}, {j, k, l}, {m, n, o}}

A simplified version of 1066's ReplacePart

ReplacePart[{4 -> Join[list[[4]], list[[5]]], 5 -> Nothing}] @ list

{{a, b, c, d}, {e, f}, {g, h, i}, {j, k, l}, {m, n, o}}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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