Message Boards Message Boards

1
|
9134 Views
|
11 Replies
|
15 Total Likes
View groups...
Share
Share this post:

How to contract a list?

I would like to "contract" a list of any length $k$, consisting of $n=2$ repeating elements, so that all repetitions within the sequence are deleted:

In[1]:= {a, a, b, b, a, b, b, b, a, a, b, b, a};
Out= {a, b, a, b, a, b, a} (*desired output*)

Or in the case of $n=3$:

In[2]:= {b, a, a, c, a, b, b, c, c, b, a, a, a, b, c, c, c, a, a}
Out= {b, a, c, a, b, c, b, a, b, c, a} (*desired output*)

I am thinking of FoldList or Fold but cannot figure out how to get there in the most succinct manner. Pattern matching also allowed. Thanks in advance for your help!

POSTED BY: Raspi Rascal
11 Replies
Posted 3 years ago

and a recursive version:

contract[{rest___, (last_) ..}] := Append[contract[{rest}], last]
contract[{}] := {}
POSTED BY: Oliver Seipel
Posted 3 years ago

a faster version based on Split:

Map[First, Split[list]]
POSTED BY: Oliver Seipel

My pleasure Raspi, luck with your book!

Hello Raspi,

here is an obvious way based on a replacement:

anylist //. {start___, PatternSequence[e_, e_], end___} :> {start, e, end}

But I would prefer Franciscos method using Split.

POSTED BY: Henrik Schachner

Thank you so much @Henrik for the interesting coding alternative, which I wasn't able to figure out on my own (pattern matching). I learn, forget, need to relearn, forget again, omg.

Actually I am writing a book (a solutions manual to a high school math text) and I have included a link to this discussion. So your coding contributions add permanent value to my book, thanks again!!

Happy New Year @everyone!

POSTED BY: Raspi Rascal

Actually i am writing a book ...

Ahhhh, therefore the reference to LaTeX in one of your recent posts and all these challenging problems! Surely a good project - always glad to help!

POSTED BY: Henrik Schachner

In a similar vein, with SequenceReplace:
SequenceReplace[anylist, {Repeated[v_]} :> v]

POSTED BY: Jesse Friedman

Hi Raspi. The following code will do it: listica = {a, a, b, b, a, b, b, b, a, a, b, b, a}; Flatten[Map[Union, Split[listica]]]

Also works for the other list you provided. Hope this helps Francisco

Oh today I wasn't aware of the Split function, my restricted active vocabulary is embarrassing. @Mike i am still the original beginner, haha! Yes, this solves the problem beautifully, very succinct, thank you very much @Francisco, appreciated!

Great community here!

POSTED BY: Raspi Rascal
Posted 3 years ago

@Raspi:

You are too humble.

Have a great and safe New Year.

POSTED BY: Mike Besso

Or simply:

In[1]:= Split[listica][[All, 1]]
Out[1]= {a, b, a, b, a, b, a}

As an aside, although not particularly relevant here: note that Union always sorts its result into canonical order. If you don't need that behavior, DeleteDuplicates is often much faster:

In[2]:= RepeatedTiming[Union@RandomChoice[{a, b, c}, 10000000];]
Out[2]= {2.76162, Null}

In[3]:= RepeatedTiming[DeleteDuplicates@RandomChoice[{a, b, c}, 10000000];]
Out[3]= {0.674569, Null}
POSTED BY: Jesse Friedman
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract