4
$\begingroup$

I have two list to process.Their first of each 2D part increasing monotonically and without repetition.

SeedRandom[1]
list1=Sort@Transpose[{RandomSample[Range@9,5],RandomSample[Range@9,5]}]

{{1,9},{2,1},{3,3},{6,4},{7,7}}

and

SeedRandom[2]
list2=Sort@Transpose[{RandomSample[Range@9,5],RandomSample[Range@9,5]}]

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

I want to inset some 2-dimension(such as $\{n,n\}$) list into place when the first element is incomplete.Like the two place where I have highlight it with red arrow

enter image description here

This is my solution for this

addElement[list_List] := Module[{pre},
  pre = Array[{#, #} &, Max[First /@ list]];
  Union[list, 
   Complement[pre, list, SameTest -> (Equal @@ First /@ {##} &)]]]

enter image description here

But I couldn't bear this ugly code.Can any elegant method do this?

$\endgroup$
4
  • 1
    $\begingroup$ Are the lists always sorted like this, with the first of each 2D part increasing monotonically? $\endgroup$ Commented Jun 3, 2016 at 20:45
  • $\begingroup$ @MariusLadegårdMeyer Actually this is this post's permutations,I will show I how to get this test list in my later edit. $\endgroup$
    – yode
    Commented Jun 3, 2016 at 20:48
  • $\begingroup$ With[{c = Complement[Range[1, #[[-1, 1]]], #[[All, 1]]]}, Union[#, Transpose[{c, c}]]] & does what I think you're after, and much more quickly. $\endgroup$
    – ciao
    Commented Jun 3, 2016 at 21:03
  • $\begingroup$ @ciao Look nice than me.Could you post it as an a solution? $\endgroup$
    – yode
    Commented Jun 3, 2016 at 21:09

2 Answers 2

3
$\begingroup$

Per request, from the comment, this appears to do what you're after, much more quickly for large cases:

 With[{c = Complement[Range[1, #[[-1, 1]]], #[[All, 1]]]}, Union[#, Transpose[{c, c}]]] & 

This appears faster yet:

Module[{a, b}, a = b = Range[1, #[[-1, 1]]]; 
               b[[#[[All, 1]]]] = #[[All, 2]]; Transpose[{a, b}]] &
$\endgroup$
2
  • 1
    $\begingroup$ @Mr.Wizard - good catch, fixed for purity and essence... $\endgroup$
    – ciao
    Commented Jun 3, 2016 at 23:44
  • $\begingroup$ The last method is wonderful $\endgroup$
    – yode
    Commented Jun 4, 2016 at 1:03
1
$\begingroup$

If your lists are not going to be very long, pure pattern stuff is easy to read:

addElems[list_List] := 
list //. {
{x___, s1 : {n1_, _}, s2 : {n2_, _}, y___} /; 
 n2 - n1 != 1 :> {x, s1, {n1, n1} + 1, s2, y}, 
{s : {n1_, _}, y___} /; n1 > 1 :> {{n1, n1} - 1, s, y}
}

This is going to be very slow if the lists get long, but I thought it was more "elegant", as you asked for.

Another easy-to-read alternative is

addElems2[list_List] := With[{ns = list[[All,1]]},
  ReplacePart[Table[{i, i}, {i, Last@ns}], Thread[ns -> list]]
]
$\endgroup$
4
  • $\begingroup$ Thanks a lot.It seem the pattern is my Achilles'heel. :) $\endgroup$
    – yode
    Commented Jun 3, 2016 at 21:13
  • $\begingroup$ Misses filling leading entries. $\endgroup$
    – ciao
    Commented Jun 3, 2016 at 21:31
  • $\begingroup$ +1 on the second, pretty efficient (first is pretty, but as you noted, BlankNullSequence is a killer...) $\endgroup$
    – ciao
    Commented Jun 3, 2016 at 23:11
  • $\begingroup$ Yeah, I would never use patterns like this if the lists were long or I needed speed. Thanks :) $\endgroup$ Commented Jun 3, 2016 at 23:13

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.