Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

What's the best way to join two consecutive lists in a list of lists ?

For example if I have the list

x = {{1}, {2}, {3}, {4}} 

and I want to get in x

{{1}, {2, 3}, {4}}.

I want to join arbitrary positions.

Edit

I want to do this using the least amount of extra memory. Imagine that instead of having numbers I have big lists.

share|improve this question
4  
Could you explain why not just {{1, 2}, {3, 4}} or {{1, 2}, {3}, {4}} instead of {{1}, {2, 3}, {4}} ? –  Artes Jan 3 '13 at 22:43
    
Maybe give a more detailed example. Is it the 2nd and 3rd elements that should be joined or the 2nd and 3rd last elements that should be joined? ...or maybe the middle 2 elements joined?? To much ambiguity. –  Mike Honeychurch Jan 3 '13 at 23:04
    
what I mean by my comment is what result do you want from this list: {{1}, {2}, {3}, {4}, {5}} –  Mike Honeychurch Jan 3 '13 at 23:34
    
By using part I think the answer of 2013 is the most memory efficient. –  faysou Jan 4 '13 at 17:40
    
Your edit is important information since I'm sure some of these answers would be quite different if they knew up front that you are working with big lists rather than 4 integers. –  Mike Honeychurch Jan 5 '13 at 4:50

4 Answers 4

list = {{1}, {2}, {3}, {4}}

I asked some questions in my comments but in the absence of clarification about what you want, i.e. will this always be applied to 4 element lists, why not just this:

list[[2]] = Flatten[list[[{2, 3}]]];
list[[3]] = Sequence[];
list

(* {{1}, {2, 3}, {4}} *)

or if you want to make it a function -- probably unnecessary because it is a straightforward two step process:

newList[list_List] := Module[{tmp = list}, tmp[[2]] = Flatten[tmp[[{2, 3}]]];
tmp[[3]] = Sequence[]; tmp]

Edit

Since you've said in your edit 4 hours ago that your actual example is big lists in place of the 4 numbers so you probably won't want to display output

list[[2]] = Flatten[list[[{2, 3}]]];
list[[3]] = Sequence[];
list;

or

list[[2]] = Flatten[list[[{2, 3}]]];
list = Delete[list, 3];

newList2[list_List] := Module[{tmp = list}, tmp[[2]] = Flatten[tmp[[{2, 3}]]];
Delete[tmp, 3]]
share|improve this answer
1  
You should note that list[[3]] = Sequence[]; does not delete elements; evaluation must take place. Do that and you'll get my vote as I was going to suggest the same method. –  Mr.Wizard Jan 4 '13 at 21:39
    
If you mean that you have to evaluate list as a final step why is that problem? In all methods you have to undertake evaluation steps. In this one the final step is different to other methods. –  Mike Honeychurch Jan 4 '13 at 21:57
    
Reading his edit if he is actually working with large lists he probably won't want to display. I'll make a revision for that case. –  Mike Honeychurch Jan 4 '13 at 22:11
1  
Mike, my point is that after making a list[[__]] = Sequence[] assignment you haven't deleted those elements (which I think you know). This could be very confusing if you then make further assignments with Part as you won't get what you (might) expect. A simple list = list; would do but so would Drop (more flexible than Delete). Anyway, +1. –  Mr.Wizard Jan 4 '13 at 23:23
1  
@sebhofer IMHO that's far from a useless question. You can see the value by using my step function, e.g. list = Range@5; list[[3]] = Sequence[]; step[list]. I wrote that function to handle just such cases as this. –  Mr.Wizard Jan 5 '13 at 18:24

A bit more general version with Drop and ReplacePart:

list = List /@ Range@8
{from, to} = {3, 6}; (* specify first and last positions to be joined *)
ReplacePart[Drop[list, {from + 1, to}], from -> Join @@ Take[list, {from, to}]]
{{1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}}

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

With ReplaceAll and Repeated:

list /. {x : Repeated[_, {from-1}], y : Repeated[_, {to-from+1}], z___} :> {x, Join@y, z}
{{1}, {2}, {3, 4, 5, 6}, {7}, {8}}
share|improve this answer

Belisarius' answer works well if you are willing to work with indexes. If you prefer to work in terms of the list elements rather than their positions, here is a rule-based solution.

innerJoin[data : {{_} ..}, a_, b_] := 
  data /. {x___, y : PatternSequence[{a}, ___, {b}], z___} :> {x, Flatten[{y}], z}

innerJoin[{{1}, {2}, {3}, {4}}, 2, 3]

{{1}, {2, 3}, {4}}

innerJoin[{{a}, {b}, {c}, {d}}, a, c]

{{a, b, c}, {d}}

Edit -- new and improved algorithm featuring the under appreciated PatternSequence :-)

share|improve this answer
    
Now with the OP's edit, I don't see how specifying the starting and ending elements would be a good idea if he wants to join 2 consecutive big lists. The Flatten would also fail if the elements are lists themselves –  Rojo Jan 5 '13 at 4:06
    
@Rojo. You're right but I didn't have that information when I wrote this answer. –  m_goldberg Jan 5 '13 at 4:19
l = {{a}, {b}, {c}, {d}};
j[l_, from_, to_] := {Sequence @@ l[[1 ;; from - 1]], Join @@ l[[from ;; to]], 
                      Sequence @@ l[[to + 1 ;;]]}

j[l, 2, 4]
(*
->{{a}, {b, c, d}}
*)
share|improve this answer
    
This is a bit terse. The OP may well need and deserve a little explanation to go with it. –  m_goldberg Jan 4 '13 at 2:13
    
@m_goldberg Feel free to improve the answer in any way you feel it should be done. The OP isn't asking for a Mma course, so it's up to you to interpret his/her need. –  belisarius Jan 4 '13 at 2:32
    
@m_goldberg Please don't take the above comment as derogatory. We deal here with users having from none to very advanced Mma knowledge. Faysal has been active here for a long time, so I guess he's able to untangle this piece of code –  belisarius Jan 4 '13 at 2:42
    
I got your point and didn't take any offense. Rather than edit your answer, I decided to offer one of my own, –  m_goldberg Jan 4 '13 at 3:46

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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