Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I'm trying to write a function that picks out the row of a Matrix whose kth element is closest to some given number that will be given to me.

So for example,

list = Table[{i, FromCharacterCode[70 + i]}, {i, 1, 10}]
{{1, "G"}, {2, "H"}, {3, "I"}, {4, "J"}, {5, "K"}, {6, "L"}, {7,"M"}, {8, "N"}, {9, "O"}, {10, "P"}}

enter image description here

b = RandomReal[{0, 6}]
4.42427

So I want to pick the row whose 1st element is closest to 4.42427. The function should spit out

{4,"J"}

Edit

Btw, thanks to Mr. Wizard's help, my crappy code works!!

disT[l_List, bb_?NumericQ, cc_Integer] := Table[Abs[bb - l[[j, cc]]], {j, 1,Dimensions[l][[1]]}]

srcH[ll_List, bb_?NumericQ, cc_Integer] := Drop[First[Sort[Transpose[    Prepend[Transpose[ll], disT[ll, bb, cc]]], #1[[1]] < #2[[1]] &]],1]


disT[list,b,1]
{3.42427, 2.42427, 1.42427, 0.42427, 0.57573, 1.57573, 2.57573,3.57573, 4.57573,5.57573}

srcH[list, b, 1]
{4, "J"}

Now I will Implement Mr. Wizard's code or Daniel's code for my actual problem. Thanks!!

Edit2

To expand on what I wrote under Mr. Wizard's answer. The actual task that I am trying to accomplish involves many lists $list_k \; k \; \in \{1,100\}$ and many comparison lists $b_k = (b_{k1},...,b_{kj}), \; \; k \; \in \{1,100\}$ .

So For example:

 list[57]=  {{1, "G"}, {2, "H"}, {3, "I"}, {4, "J"}, {5, "K"}, {6, "L"}, {7,"M"}, {8, "N"}, {9, "O"}, {10, "P"}}

 b[57]={0.1,7.3,9.8}

 list[79]=  {{2.8, "G"}, {3.4, "H"}, {4.5, "I"}, {5.1, "J"}, {6.05, "K"}, {7.1, "L"}, {8.3,"M"}, {8.5, "N"}, {9, "O"}, {10, "P"}}

 b[79]={5,7.2,8.1}

and my final output, as index goes from 1 to 100, will find rows where the first element is close to the elements of b[k] respectively:

 output[57]={{1,G},{7,M},{10,P}}
 output[79]={{5.1,J},{7.1,L},{8.3,M}}

I was planning on using the function I got from the help here at mma.se inside a table or something but since Mr. Wizard has mentioned speeding up computation, I figured it would be best if I described the exact problem I am working on.

share|improve this question
    
How are you measuring distance from a real to a character? –  Daniel Lichtblau Oct 10 '12 at 23:33
    
@DanielLichtblau I only want to use the Distance function on columns which have real entries. –  Amatya Oct 10 '12 at 23:51
    
You mean the row whose first element is closest, right? –  Rojo Oct 11 '12 at 0:55
    
@Rojo in this example, the first element but in my actual problem some kth element. –  Amatya Oct 11 '12 at 1:10
    
@Rojo and Daniel .. I just noticed and fixed the typo in my question. –  Amatya Oct 11 '12 at 1:31

2 Answers 2

up vote 2 down vote accepted

The reason I wanted this as a function is because I will wind up using it on lots of different lists for lots of different columns. I'm guess the function form is better for that.

If you are going to be using the function nearly at random, with little repetition of lists then you may do well with:

nff[num_?NumericQ, l_List] := Nearest[#[[1]] -> # & /@ list, b, 1][[1]]

If you will use the function for many columns within a single list I propose that you let Nearest built a function for you. If memory is not a limitation (the lists are not too large) then I propose using memoization to streamline this process.

m : makeNF[list_List] := m = Nearest[#[[1]] -> # & /@ list]

nffmem[num_?NumericQ, l_List] := makeNF[l][num][[1]]

This pair of functions will build a Nearest function only once for each list, caching it as a definition of makeNF. You could use ClearAll[makeNF] and then evaluate the code above to clear these cached values if memory starts to get low.

share|improve this answer
    
I just looked up memoization on wikipedia. It will take be a bit to appreciate and understand the differences between the two ways you described. To address your comment, I actually have a list of 20 different numbers each for about a 100 Matrices. So b , the comparison number, is itself a list and for each of those b's I want to find something in column k closest to it. Then I do this for a 100 Matrices, each with a unique b. This is for one set of overall parameters. So I might wind up doing 2000 such uses of the function, many many times. –  Amatya Oct 11 '12 at 7:09
    
@Amatya I'll be in chat for a few minutes if you want to discuss this. –  Mr.Wizard Oct 11 '12 at 22:43

Use Nearest.

nf = Nearest[Map[Rule[#[[1]], #] &, list]];

nf[b][[1]]
{4, "J"}
share|improve this answer
    
Geez man, format your code! ;-p –  Mr.Wizard Oct 10 '12 at 23:48
    
Oh man! good MMA code is so slick! Thanks a lot Daniel! What was I doing wrong in my disT function though? –  Amatya Oct 10 '12 at 23:53
1  
Shorter: nf = Nearest[#[[1]] -> # & /@ list] –  Mr.Wizard Oct 11 '12 at 0:04
1  
@Amatya you're using incorrect patterns. As written you're trying to match objects with heads list and numba which are not built-in heads in Mathematica. Also, if you are going to write this as a function that is called as shown, rather than building a function nf as Daniel's answer does, you would to better to use a different syntax for Nearest. Try this: nff[num_?NumericQ, l_List] := Nearest[#[[1]] -> # & /@ list, b, 1][[1]] –  Mr.Wizard Oct 11 '12 at 0:08
4  
@Amatya see this slide for a summary of pattern objects. There are quite a few of them! –  Mr.Wizard Oct 11 '12 at 0:20

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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