# Find the list that best matches reference list

I need to find how well several different lists match a reference list. I'm looking for a percentage or some kind of similarity score.

For example,

a = {"A278", "G279", "S280", "G281", "I282", "I283", "I284", "S285",
"D286", "T287", "P288", "V289", "H290", "D291", "C292"}
b = {"S280", "G281", "I282", "I284"}
c = {"C275", "S276", "T277", "A278", "G279"}


How can I determine that b is a better match against a than c? a is the reference list.

Order matters.

After looking through the documentation, the only way I can think of doing this is to iterate through b and c and test if each element is MemberQ of a, tallying up the total and comparing the totals at the end. Is there a better approach?

• You might consider looking through the whole bunch of *Distance[]/*Dissimilarity[] functions available. SequenceAlignment[] might also be of use. – J. M.'s discontentment Oct 8 '18 at 4:24
• Testing as described in the last paragraph of the question does not take account of order. If order actually does not matter, consider Complement. – bbgodfrey Oct 8 '18 at 4:33
• Working on Complement now, it seems promising @bbgodfrey – briennakh Oct 8 '18 at 4:37

Maybe:

LongestCommonSequence[a, b]


{"S280", "G281", "I282", "I284"}

LongestCommonSequence[a, c]


{"A278", "G279"}

Length@LongestCommonSequence[a, #] & /@ {b, c}


{4, 2}

MaximalBy[Length[a⋂#]&]@{b,c}


{{"S280", "G281", "I282", "I284"}}

MinimalBy[Length@Complement[a,#]&]@{b,c}


{{"S280", "G281", "I282", "I284"}}

• +1 for conciseness, this is better than my answer – briennakh Oct 8 '18 at 5:21
• @briennakh, yours is probably faster. – kglr Oct 8 '18 at 5:22

Going off your percent similarity idea, maybe something like

listsim[ref_, test_] := {#, 100. (1 - Length@Complement[ref, #]/Length@ref)} & /@ test

listsim[a, {a, b, c}]


{{{A278,G279,S280,G281,I282,I283,I284,S285,D286,T287,P288,V289,H290,D291,C292},100.} {{S280,G281,I282,I284},26.6667}
{{C275,S276,T277,A278,G279},13.3333}}

which ended up being in a similar vein to your answer.

• I like this!! Thanks! – briennakh Oct 8 '18 at 5:18

Suppose I have the reference list a and a matrix otherLists of all other lists I want to compare against a:

otherLists[[Ordering[Length[#] & /@ (Complement[a, #] & /@ otherLists), 1]]]


This will return the list that best matches a.

• you can use just Length instead of Length[#] &. – kglr Oct 8 '18 at 5:28
• Please don't edit my answer @MarcoB — Write a comment. – briennakh Feb 20 '19 at 18:18
• I rolled back my changes. @kglr 's comment is suggesting the same change. Is there a reason you prefer to retain your version? – MarcoB Feb 20 '19 at 18:21
• My answer works. If you want to optimize my answer, you can add your suggestion as a comment or upvote kglr's comment. Thank you. @MarcoB – briennakh Feb 20 '19 at 18:23
• @briennakh It certainly works, but the usage of Length[#]& where Length would suffice is unnecessary. This site is collaboratively edited, so I made a change that, in my opinion, improved this answer for future readers. Anyway, I will leave it as it was; perhaps you might consider making a change yourself. – MarcoB Feb 20 '19 at 18:33