3
$\begingroup$

I'm trying to solve a heuristic search in Mathematica 9. I get a list of succesor nodes called open with two nodes and a heuristic value, e.g.,

open={{node1,node2,H1},...,{node2,node1,Hi},...,{noden,noden,Hn}}

I need to select only when the two first elements are the same (no matter order) but where the heuristic is lower. Following the code that I used for sort the elements by the first item

Sort[open, #1[[1]] < #2[[1]] &]

I try to select cases when the same first and second numbers and the heuristic value where lower:

Select[open, #1[[1]]==#2[[1]] &&  #1[[2]] == #2[[2]] && #1[[3]]< #2[[3]] &]

But, returns {}...

My list

open = {{1, 2, 3}, {2, 1, 5}, {1, 2, 2}, {3, 4, 5}, {4, 3, 2}};

Between {1, 2, 3}, {1, 2, 2}, and {2, 1, 5} then choose {1, 2, 2} that has the lower heuristic. And, between {3, 4, 5} and {4, 3, 2} then {4, 3, 2}...

{{1, 2, 2},{4, 3, 2}}

Thanks,

$\endgroup$
  • $\begingroup$ Just as a remark: in your Select statement, you're using #2, but this won't do anything. The function in Select is a function of 1 argument only and the #2 slot will never be filled. $\endgroup$ – Sjoerd Smit Jul 29 '17 at 19:09
3
$\begingroup$

You can try something like this:

First[Sort[#, #1[[3]] < #2[[3]] &]]&/@Gather[open, Complement[Most[#1], Most[#2]] === {}&]

{{1, 2, 2}, {4, 3, 2}}

this is a combination of two functions: First you gather the same edges and then you sort them according to their weight and take the first element (which has the lowest value.)

$\endgroup$
  • $\begingroup$ Thanks, but can you explain me a little deeper what did you do? especially, the last part... $\endgroup$ – Jotasmall Jun 5 '13 at 14:22
  • $\begingroup$ @user7892 If you mean the Complement[Most[#1], Most[#2]] === {} part, it's just a way using basic principles from set theory for gathering the same edges. $\endgroup$ – Spawn1701D Jun 5 '13 at 15:22
  • $\begingroup$ I did an effort to get it...yeah, in that part, you drop out the ones with same two firsts member. Thanks again, $\endgroup$ – Jotasmall Jun 5 '13 at 19:47
3
$\begingroup$

A combination of GatherBy[] and SortBy[] does the trick:

First[SortBy[#, Last]] & /@
GatherBy[{{1, 2, 3}, {2, 1, 5}, {1, 2, 2}, {3, 4, 5}, {4, 3, 2}}, Sort[Take[#, 2]] &]
   {{1, 2, 2}, {4, 3, 2}}
$\endgroup$
0
$\begingroup$

In versions 10+, you can use MinimalBy combined with GroupBy:

open = {{1, 2, 3}, {2, 1, 5}, {1, 2, 2}, {3, 4, 5}, {4, 3, 2}};

Values @ GroupBy[open, Sort[#[[;; 2]]] &, First @ MinimalBy @ Last]

{{1, 2, 2}, {4, 3, 2}}

Or, MinimalBy combined with Merge

Values @ Merge[First @ MinimalBy @ Last][Sort[#[[;;2]]] -> # &/@ open]

{{1, 2, 2}, {4, 3, 2}}

Or, combined with GatherBy:

First @ MinimalBy[Last] /@ GatherBy[open, Sort[#[[;; 2]]] &]

{{1, 2, 2}, {4, 3, 2}}

For older versions, a combination of SplitBy and SortBy also works

First /@ SplitBy[SortBy[open, {Sort[#[[;;2]]]&, Last[#]&}], Sort[#[[;;2]]]&]

{{1, 2, 2}, {4, 3, 2}}

$\endgroup$
  • $\begingroup$ Pardon me, but none of these seem better than J.M.'s GatherBy method. Would choose any of these in practice over it, and why? $\endgroup$ – Mr.Wizard Jul 29 '17 at 17:33
  • 2
    $\begingroup$ @Mr.Wizard, no claim is made about better:) $\endgroup$ – kglr Jul 29 '17 at 17:35

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.