3
$\begingroup$

I have a list whose elements consist of a date object followed by several integers:

lis1 = {{desiredDate, 1, 2}, {desiredDate, 3, 4}, {desiredDate, 5, 6}, {desiredDate, 7, 8}};

I have a similarly structured list with dates that may extend from one to four days before desiredDate:

lis2 = {{undesiredDate, 1, 2},{undesiredDate, 5, 6}}

I would like to remove from lis1 all elements where the non-date elements of lis2 match, to give:

res = {desiredDate, 3, 4},{desiredDate, 7, 8}}

Thanks for ideas on how to do this.

$\endgroup$
1
  • 1
    $\begingroup$ Select[lis1, ! MemberQ[Rest /@ lis2, Rest[#]] &] $\endgroup$
    – Bob Hanlon
    Sep 23 at 19:04
3
$\begingroup$
DeleteCases[lis1, Alternatives @@ ({_, ##2} & @@@ lis2)]
{{desiredDate, 3, 4}, {desiredDate, 7, 8}}
$\endgroup$
2
  • $\begingroup$ I would like to learn more about ## usage. Can you please suggest a resource? $\endgroup$
    – Syed
    Sep 24 at 6:28
  • 1
    $\begingroup$ @Syed, see SlotSequence in the docs. (Or highlight ## in the input notebook and hit F1). $\endgroup$
    – kglr
    Sep 24 at 6:34
2
$\begingroup$

signatures to be removed if found matching Rest@lis1:

signature = Rest /@ lis2

{{1, 2}, {5, 6}}

Write a function that tests membership and deletes matching signatures:

f[k_List, s_List] := If[MemberQ[s, Rest@k ], Nothing, k]

Execute:

f[#, signature] & /@ lis1

{{desiredDate, 3, 4}, {desiredDate, 7, 8}}

$\endgroup$
1
$\begingroup$

If I understand correctly, you want to remove items from lis1 that have a date 0 to 4 days later than any date in lis2.

Toward this aim, you could use DayCount. Then:

((0 <= # <= 4) & /@ (DayCount[lis2, #])) &

is a function that returns a list of True/False if the argument is 0 to 4 days before the entries in lis2. Or and negation will give True if the argument is NOT in any of these intervals:

! Or @@ ((0 <= # <= 4) & /@ (DayCount[lis2, #])) &

Then we can use Selectto get the entries from lis1 we want. Here is an example:

d1 = DateObject[{2010, 4, 2}, "Day", "Gregorian", 1.`];
d2 = DateObject[{2013, 11, 12}, "Day", "Gregorian", 1.`];
d3 = DateObject[{2017, 2, 3}, "Day", "Gregorian", 1.`];
n1 = DateObject[{2010, 4, 1}, "Day", "Gregorian", 1.`];
n2 = DateObject[{2013, 11, 12}, "Day", "Gregorian", 1.`];
lis1 = {d1,  d2, d3};
lis2 = {n1, n2};

Select[lis1, ! Or @@ ((0 <= # <= 4) & /@ (DayCount[lis2, #])) &]

enter image description here

$\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.