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
$\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$
  • $\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 '18 at 21:35
  • $\begingroup$ @Suite401 What modification? Please add it to the question. $\endgroup$ – C. E. May 22 '18 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 '18 at 21:44
  • $\begingroup$ @Suite401 Added a solution for that list to my answer. $\endgroup$ – C. E. May 22 '18 at 21:51
  • $\begingroup$ Thanks yes this works. $\endgroup$ – Suite401 May 22 '18 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, privacy policy and cookie policy

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