6

I have two lists: list1 and list2:

list1 = {{"TSC" \[DirectedEdge] "FIN", 22}, {"CO12" \[DirectedEdge] "AGF", 
21}, {"MA2" \[DirectedEdge] "EGW", 20}, {"MA1" \[DirectedEdge] "FIN", 
19}, {"FIN" \[DirectedEdge] "CO12", 18}, {"EGW" \[DirectedEdge] "TSC", 
17}, {"FIN" \[DirectedEdge] "MA2", 16}, {"CO12" \[DirectedEdge] "MA1", 
14}, {"AGF" \[DirectedEdge] "MA2", 13}, {"MA2" \[DirectedEdge] "AGF", 
12}, {"AGF" \[DirectedEdge] "CO12", 11}, {"CST" \[DirectedEdge] "MA2", 
10}, {"EST" \[DirectedEdge] "CO12", 9}, {"MA2" \[DirectedEdge] "CST", 
8}, {"FIN" \[DirectedEdge] "TSC", 7}, {"EST" \[DirectedEdge] "MA1", 
6}, {"EGW" \[DirectedEdge] "CST", 5}, {"CST" \[DirectedEdge] "EGW", 
4}, {"AGF" \[DirectedEdge] "CST", 2}};

list2 = {"MA2" [DirectedEdge] "AGF", "AGF" [DirectedEdge] "MA2", "AGF" [DirectedEdge] "CST", "FIN" [DirectedEdge] "CO12", "MA1" [DirectedEdge] "FIN", "FIN" [DirectedEdge] "MA2", "EGW" [DirectedEdge] "TSC"};

I want to select those {x, y} pairs from list1 using elements (x) in list2, and then take the average of the ys that are already selected. I like to do it in one-liner code.

I tried:

Mean[Select[list1, MemberQ[#, list2] &][[All,2]]]

with no success. I tried many other codes available in this forum but I cannot get what I want.

Tugrul Temel
  • 6,193
  • 3
  • 12
  • 32

5 Answers5

8

As shown by other answers, there are many solutions for one problem in Mathematica.

List

MemberQ

Select[list1,MemberQ[list2,#[[1]]]&][[All,2]]//RepeatedTiming
(*{0.0000154381,{19,18,17,16,13,12,2}}*)

Cases[list1,{edge_,int_}/;MemberQ[list2,edge]:>int]//RepeatedTiming ({0.0000130373,{19,18,17,16,13,12,2}})

Alternatives is faster since it's purely a pattern

Cases[list1,{Alternatives@@list2,int_}:>int]//RepeatedTiming
(*{5.47926·10^-6,{19,18,17,16,13,12,2}}*)

Set

Intersection has an option SameTest. The effect is that Intersection[A,B,SameTest->f] returns the intersection of A by B according to f

Intersection[list1,list2,SameTest->(First[#1]===#2&)][[All,2]]//RepeatedTiming
(*{0.000107458,{2,13,17,18,16,19,12}}*)

Notice that Intersection is a set-theoretical function, hence it breaks the original order and is slower.

Association

This is realized by @Syed. In my experience, this approach is more suitable when dealing with dataset.

  • The code is more readable/maintainable. If querying the data with more complicated requirements, the level specification in the list/set approach is much harder to track (imagine that there are lots of [[All,1;;-1;;2]]... )

  • Association has better performance than List, see e.g. How to make use of Associations?

  • support SQL-like operations, see guide/DatabaseLikeOperationsOnDatasets

For simple tasks there seems no significant difference between these two approaches.

Lacia
  • 2,253
  • 3
  • 19
5
result = Rule @@@ list1 // KeyTake[list2] // Values

{12, 13, 2, 18, 19, 16, 17}

result // Mean

97/7

eldo
  • 67,911
  • 5
  • 60
  • 168
3

Using KeySelect:

asc1 = (First@# -> Last@#) & /@ list1
Values@KeySelect[asc1, MemberQ[list2, #] &]

{19, 18, 17, 16, 13, 12, 2}

To get the mean:

Mean@Values@KeySelect[asc1, MemberQ[list2, #] &]

Using Position and Extract:

Extract[list1
   , Position[
    Position[list2, #] & /@ list1[[All, 1]]
    , Except[{}], 1, Heads -> False]
   ] // Map[Last] // Mean
Syed
  • 52,495
  • 4
  • 30
  • 85
2

Try this:

f[rule_] := Map[If[MemberQ[#, rule], #, Nothing] &, list1];
lst = Flatten[Map[f[#] &, list2], 1]

(* {{"MA2" [DirectedEdge] "AGF", 12}, {"AGF" [DirectedEdge] "MA2", 13}, {"AGF" [DirectedEdge] "CST", 2}, {"FIN" [DirectedEdge] "CO12", 18}, {"MA1" [DirectedEdge] "FIN", 19}, {"FIN" [DirectedEdge] "MA2", 16}, {"EGW" [DirectedEdge] "TSC", 17}} *)

Mean[Transpose[lst][[2]]]

(* 97/7 *)

Have fun!

Alexei Boulbitch
  • 39,397
  • 2
  • 47
  • 96
2
Extract[list1[[All,2]],Position[list1[[All,1]],Alternatives@@list2]]//Mean

(* 97/7 *) 

Perhaps a more readable version:

 Extract[list1,Position[list1,Alternatives@@list2].{{1,0},{0,2}}]//Mean

(* 97/7 *)

Or, usingPart rather than Extract:

list1[[All,2]][[(list1//Position[Alternatives@@list2])[[All,1]]]]//Mean

(* 97/7 *)

user1066
  • 17,923
  • 3
  • 31
  • 49