3
$\begingroup$

I need to identify the position inside list of the elements in target. Straightforward solution:

Timing[target // Map[Position[list, #] &] ;

15s

I needed a faster algorithm for my real case. Here is my try but any completely different solution is also very welcome. I assigned a score to each element, compared scores first, then look for the specific element within the candidates.

Timing[target // Map[identifyTerms];]

2.5s

But this is still not fast enough (in the real case)

Here my dummy example I made for this question:

(*list and target*)

list = {a, b, c, d, e, f, g, h} // Permutations[#, {2, 7}] & // 
    RandomSample // Map[Dot @@ # &];

target = {a, b, c, d, e, f} // Permutations[#, {2, 5}] & // 
   Map[Dot @@ # &];

(*simple target: target={a.b.c}*)
(*simple list: list={a, b.f, a.b.c}*)


(*functions*)

getScore[expr_] := 
 expr /. {a -> 1, b -> 2, c -> 3, d -> 4, e -> 5, f -> 6, g -> 7, 
    h -> 8} /. Dot -> Times

listScores = list // getScore;
identifyTerms[expr_] := Module[{cand, p},
   cand = Position[listScores, getScore[expr]] // Flatten;
   p = Position[list[[cand]], expr] // Flatten;
   cand[[p]]];
$\endgroup$
8
  • $\begingroup$ A solution would be to make the scores unique by changing getScore, but I cannot play around with this function since it's used in many other places... I guess I could define a completely new one $\endgroup$
    – Albercoc
    Commented Apr 4, 2023 at 10:35
  • 3
    $\begingroup$ Could you give a more minimal example that's a little easier to play with? $\endgroup$ Commented Apr 4, 2023 at 11:18
  • 1
    $\begingroup$ Am I correct in understanding that this code does just FirstPosition[list, #, {1}, Heads -> False] & /@ target? Or alternatively Lookup[PositionIndex[list], target] $\endgroup$ Commented Apr 4, 2023 at 13:42
  • 1
    $\begingroup$ In that case Lookup[PositionIndex[list], target] should do what you need, but much faster (basically instantaneously for me). Does that answer your question? $\endgroup$ Commented Apr 4, 2023 at 15:17
  • 1
    $\begingroup$ I could post my answer, or you promote your comment to answer and I'll accept it. $\endgroup$
    – Albercoc
    Commented Apr 5, 2023 at 10:09

1 Answer 1

6
$\begingroup$

As discussed in the comments, the best way to solve this problem is to first use PositionIndex to create a hash table up front so WL doesn't have to keep doing the same thing over and over:

posInd = PositionIndex[list];
Lookup[posInd, target]

or

Lookup[posInd, #]& /@ target
$\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.