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
    Commented Sep 23, 2021 at 19:04

3 Answers 3

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
    Commented Sep 24, 2021 at 6:28
  • 1
    $\begingroup$ @Syed, see SlotSequence in the docs. (Or highlight ## in the input notebook and hit F1). $\endgroup$
    – kglr
    Commented Sep 24, 2021 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 and acknowledge you have read our privacy policy.

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