1
$\begingroup$

I am trying to learn how Associations work differently from lists. I have read Seth Chandler's guide and all the documentation. What I do easily in lists seems to elude me when I use an Association. Here is a list of lists

list = {{"col1", "col2", "col3", "col4"}, {"a", 15, "c", "d"}, {"e", 
9, "f", "g"}, {"h", "cat", "d", "s"}, {"dog", "cat", "owl", 
"ferret"}, {"stove", "refrig", "dish", "fork"}, {"land", "water", 
"sea", "fire"}, {"if", 15, "and", "but"}, {"either", 9, "or", 
"maybe"}, {"w", "x", "y", "z"}, {"in", "cat", "out", "with"}};

This makes the list of lists an Association

 listToAssociation[data : {__List}, head___List, 
      OptionsPattern[{"headers" -> True}]] :=
        If[OptionValue["headers"]
           , Inner[Rule, data[[1]], #, Association] & /@ data[[2 ;; All]]
           , Inner[Rule, head, #, Association] & /@ data[[2 ;; All]]
         ];
     assocTest = listToAssociation[list, "headers" -> True];

And this groups by col2

q1 = Query[GroupBy[#col2 &]][assocTest]

Note that the second element in each list (column 2) has repeated values (9 and 15 each appear twice and "cat" appears three times)

I need a query that chooses those lists having duplicate elements in them, counts the number of times each duplicate appears. Using lists, this kludge produces output that works

 countFct[list_List] := Module[{dups, cnt},
   dups = Select[GatherBy[Drop[list, 1], #[[2]] &], Length[#] > 1 &];
cnt = Length[dups[[#]]] & /@ Range[Length[dups]];
   Grid[Transpose[{cnt, dups}], Frame -> All]
   ];

which looks like this

enter image description here

Association is supposed to make this a lot easier. I have not found that to be so, yet.

$\endgroup$

1 Answer 1

0
$\begingroup$

The following code does use associations, but in a roundabout way, i.e. mostly because that's the output of GroupBy. The real advantage is the fact that GroupBy also allows the use of a combiner function that operates on each of the groups; we can take advantage of that to post-process groups and mark those without repeated entries for removal.

GroupBy[
  Rest@list,
  #[[2]] &,
  Block[{len = Length[#]},
    If[len > 1, {len, #}, Nothing]
  ] &
] // Values // Grid[#, Frame -> All] &

same grid of results as OP

I am not sure that I can see a more straight forward way to use association objects directly here. I also wanted to note that your listToAssociation function returns a list of associations, rather than a single Association object. I am not sure that a list of associations would have many advantages over a plain list of lists.

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