4
$\begingroup$

I have a list that consists of events occurring on certain dates of certain months. To simplify, the list looks like this:

list = {{"June","19","a"},{"b"},{"c"},{"August","2","d"},{"e"}}

I would like to prepend the month and date elements to each succeeding element until a new date is encountered, so as to make:

res = {{"June","19","a"},{"June","19","b"},{"June","19","c"},{"August","2","d"},{"August","2","e"}}

...and so forth. I'd like to avoid DateObjects and just work with strings.

I would like to generalize the question, by allowing the list to contain variable numbers of elements following the month/day elements:

list = {{"June","19","a","a1"},{"b","b2","b3","b4"},{"c"},{"August","2","d"},{"e","e1}} to give:


res = {{"June","19","a","a1"},{"June","19","b","b2","b3","b4"},{"June","19","c"},{"August","2","d"},{"August","2","e","e1}}
$\endgroup$

3 Answers 3

3
$\begingroup$
SequenceReplace[
  list,
  {{m_, d_, el_}, rest : {_} ...} :> 
   Sequence @@ Join[{{m, d, el}}, Join[{m, d}, #] & /@ {rest}]
  ]

{{"June", "19", "a"}, {"June", "19", "b"}, {"June", "19", "c"}, {"August", "2", "d"}, {"August", "2", "e"}}

For the modified list given in a comment below:

SequenceReplace[
 list,
 {{m_, d_, elems__}, rest : ({_} | {_, _}) ...} :> 
  Sequence @@ Join[{{m, d, elems}}, Join[{m, d}, #] & /@ {rest}]
 ]

And the most general version given can be solved like this:

months = Alternatives["January", "February", "Mars", "April", "May", 
   "June", "July", "August", "September", "October", "November", 
   "December"];

SequenceReplace[
 list,
 {{m : months, d_, elems__}, rest : {Except[months], ___} ...} :> 
  Sequence @@ Join[{{m, d, elems}}, Join[{m, d}, #] & /@ {rest}]
 ]
$\endgroup$
9
  • $\begingroup$ Thank you for the reponses Alan and C.E! They work for the test list, but fail for the following minor modification: $\endgroup$
    – Suite401
    May 22, 2018 at 21:35
  • $\begingroup$ @Suite401 What modification? Please add it to the question. $\endgroup$
    – C. E.
    May 22, 2018 at 21:43
  • $\begingroup$ Sorry I ran afoul of the time limit for adding comments: List = {{"June","19","a","a1"},{"b","b1"},{"c"},{"August","2","d"},{"e"}}, where the elements following the date may be lists consisting of more than one member. In this case, the desired result would be: {{"June", "19", "a", "a1"}, {"June", "19", "b", "b1"}, {"June", "19", "c"}, {"August", "2", "d"}, {"August", "2", "e"}} $\endgroup$
    – Suite401
    May 22, 2018 at 21:44
  • $\begingroup$ @Suite401 Added a solution for that list to my answer. $\endgroup$
    – C. E.
    May 22, 2018 at 21:51
  • $\begingroup$ Thanks yes this works. $\endgroup$
    – Suite401
    May 22, 2018 at 21:54
5
$\begingroup$
list = {{"June", "19", "a"}, {"b"}, {"c"}, {"August", "2", "d"}, {"e"}}
f[lst_] := With[{date = Most[lst[[1]]]},
  Prepend[Join[date, #] & /@ lst[[2 ;;]], First@lst]
  ]
f /@ Split[list, 1 == Length[#2] &]
$\endgroup$
0
$\begingroup$
ClearAll[f]
f = Module[{m = Split[#, 
        Not[MemberQ[DateString[{2018, #}, "MonthName"] & /@ Range[12], #2[[1]]]] &]}, 
    m[[;; , 2 ;;]] = Flatten /@ Thread[{#, #2}, List, {2}] & @@@ 
       Thread[{m[[;; , 1, ;; 2]], m[[;; , 2 ;;]]}]; 
    Join @@ m] &;

Examples:

list1 = {{"June", "19", "a"}, {"b"}, {"c"}, {"August", "2", "d"}, {"e"}};
list2 = {{"June", "19", "a", "a1"}, {"b", "b2", "b3", "b4"}, {"c"}, 
  {"August", "2", "d"}, {"e", "e1"}} ;

f /@ {list1, list2}

{{{"June", "19", "a"}, {"June", "19", "b"}, {"June", "19", "c"}, {"August", "2", "d"}, {"August", "2", "e"}},
{{"June", "19", "a", "a1"}, {"June", "19", "b", "b2", "b3", "b4"}, {"June", "19", "c"}, {"August", "2", "d"}, {"August", "2", "e", "e1"}}}

$\endgroup$

Your Answer

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

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