7
$\begingroup$

I am trying to find a neat way of applying an operation to each list element, but do not know how to properly use multiple slots or whether it is actually possible to solve this with multiple slots. I am doing the following thing:

I have defined the following objects:

assoc1 = <|{a, b} -> 5, {c, d} -> 2,  {e, f} -> -3|>;
lyst1 = {b, e, g};
lyst2 = {{b, e, g}, {a, b, c}}; 

Now, I want to select all entries in assoc1 whose key lists have a nonzero intersection with lyst1. This I can do in the following way:

KeySelect[assoc1, Intersection[lyst1, #] =!= {} &]

correctly getting the return:

<|{a, b} -> 5, {e, f} -> -3|>

And now the problem: Is there a way to elegantly do this for each list in lyst2 ? I know I could just use a for loop, but I was hoping for something shorter. I generally know how to apply a function to each element in lyst2 via "/@", but for that I would usually put a second Slot (=#) inside the Intersection function at the place where you see "lyst1" in my working example. I mean something like (knowing that this exact line does NOT do what I want):

KeySelect[assoc1, Intersection[#2, #1] =!= {} &] &/@ lyst2

where "#1" is the slot for each element in assoc1 whose key I am testing and "#2" is the slot used for looping over lyst2.

I do not know how to circumvent that or make it work with this second slot and would be very grateful for any suggestion!

$\endgroup$
4
  • 2
    $\begingroup$ Try f[v_]:=KeySelect[assoc1, Intersection[v, #] =!= {} &] and then Map[f[#]&,lyst2] or f/@lyst2 and see if either of those are acceptable $\endgroup$
    – Bill
    Mar 16, 2023 at 19:06
  • $\begingroup$ Of course it is! Thank you very much! I tried so much more complicated stuff and completely overlooked that by defining a function in this way there is no problem! If it is ok, I would leave the question open out of curiosity to see if there are other neat ideas like yours. But nevertheless, you should definitely post this not only as a comment but as an answer! $\endgroup$ Mar 16, 2023 at 19:11
  • 1
    $\begingroup$ Related: 38393. $\endgroup$
    – Syed
    Mar 16, 2023 at 19:26
  • $\begingroup$ Thanks @Syed, I was not familiar with "OperatorApplied/Curry". $\endgroup$ Mar 16, 2023 at 19:52

4 Answers 4

5
$\begingroup$

An alternative to the function that @Bill created for applying to more complex arrays is as follows:

f[v_?VectorQ] := KeySelect[assoc1, Intersection[v, #] =!= {} &]
f[v_?TensorQ] := Map[f[#] &, v]

Test:

f@lyst1
(*<|{a, b} -> 5, {e, f} -> -3|>*)
f@lyst2
(*{<|{a, b} -> 5, {e, f} -> -3|>, <|{a, b} -> 5, {c, d} -> 2|>}*)
$\endgroup$
1
  • 1
    $\begingroup$ Many thanks for your idea! $\endgroup$ Mar 17, 2023 at 10:00
6
$\begingroup$

As requested, Use function definition to separate the two applications of #

f[v_]:=KeySelect[assoc1, Intersection[v, #] =!= {} &]
Map[f[#]&,lyst2] (*or f/@lyst2 *)
$\endgroup$
1
  • 1
    $\begingroup$ Try the following so that your function applies to each list: f[v_?VectorQ] := KeySelect[assoc1, Intersection[v, #] =!= {} &]; f[v_?TensorQ] := Map[f[#] &, v];` $\endgroup$ Mar 16, 2023 at 19:29
6
$\begingroup$

Try also this:

g[lst_List] := Intersection[lst, #] != {} &;
KeySelect[assoc1, g[#]] & /@ lyst2

(*  {<|{a, b} -> 5, {e, f} -> -3|>, <|{a, b} -> 5, {c, d} -> 2|>}  *)

Have fun!

$\endgroup$
1
  • 1
    $\begingroup$ +1. In a similar vein: KeySelect[assoc1, ContainsAny[#]]& /@lyst2 $\endgroup$
    – WReach
    Mar 19, 2023 at 1:23
1
$\begingroup$
asc = <|{a, b} -> 5, {c, d} -> 2, {e, f} -> -3|>;

kv = {b, e, g};

km = {{b, e, g}, {a, b, c}};

A hash-free variant of E. Chan-López answer using ContainsAny

sel[x_?VectorQ] := KeySelect[asc, ContainsAny @ x]

sel[x_?MatrixQ] := sel /@ x

sel @ kv

<|{a, b} -> 5, {e, f} -> -3|>

sel @ km

{<|{a, b} -> 5, {e, f} -> -3|>, <|{a, b} -> 5, {c, d} -> 2|>}

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