4
$\begingroup$

So I have a list somewhat like this:

{
 {"name" -> "bob", "age" -> "20", "phone" -> "123456"},
 {"name" -> "Fred", "age" -> "40", "phone" -> "098765"}
} 

At the moment I am doing the following to pull out the related item ( y is the list).

pos = First[First[Position[y, "Fred"]]]
z = Part[y, pos]

This returns:

{"name" -> "Fred", "age" -> "40", "phone" -> "098765"}

While "Fred" won't show up in other fields, I'm not overly happy with this.

I was wondering if there is a more elegant way to find an array item based on the value of a certain field within that array?

$\endgroup$
3
  • $\begingroup$ @Xavier, looks like an answer to me. $\endgroup$ – J. M.'s torpor Oct 17 '15 at 16:47
  • $\begingroup$ @Xavier Shape it in an answer and I'll vote on it. I tried that snippet you posted and it comes back with {} . I changed list to y. $\endgroup$ – Simon O'Doherty Oct 17 '15 at 16:56
  • $\begingroup$ Possibly a list of associations would be more appropriate in your application than a list of rules, i.e. list = { <| "name" -> "bob", "age" -> "20", "phone" -> "123456" |>, <| "name" -> "Fred", "age" -> "40", "phone" -> "098765" |> } Then you can do things like list[[1]]["name"] and Select[list, #["name"] == "bob" &] $\endgroup$ – Axel Boldt Oct 18 '15 at 0:17
5
$\begingroup$

Comment posted as an answer, as suggested.


Notation

list = {
        {"name" -> "bob", "age" -> "20", "phone" -> "123456"},
        {"name" -> "Fred", "age" -> "40", "phone" -> "098765"}
       }

Possible solutions

If you are interested in getting z only, you can use

Cases[list, {_ -> "Fred", __}]

provided that the structure of all your sublists is the same as what you wrote. Alternatively, the function Select can be considered

Select[list, MatchQ[#, {_ -> "Fred", __}] &]

Those will give you all sublists where the name Fred occurs. In case there is only one item of this form, you will end up with {z} rather than z. A workaround would be

FirstCase[list, {_ -> "Fred", __}]

or

SelectFirst[list, MatchQ[#, {_ -> "Fred", __}] &]

Update

Following OP's comment, for a list of different structure one can use

 Cases[list, {___, "name" -> "Fred", ___}]

or

Select[list, MatchQ[#, {___, "name" -> "Fred", ___}] &]
$\endgroup$
5
  • 2
    $\begingroup$ Select[list, ! FreeQ[#, "Fred"] &][[1]] $\endgroup$ – Bob Hanlon Oct 17 '15 at 17:15
  • $\begingroup$ @Xavier. They work for the example, but if you change the fields position they don't appear to always works. :-/ Bob's work for say phone number, but you haven't specified an explicit field. So there is chance another field could match. $\endgroup$ – Simon O'Doherty Oct 17 '15 at 17:25
  • 1
    $\begingroup$ Although not the exact answer helped me find the answer: Select[list, ! FreeQ[#, "name" -> "Fred"] &][[1]] $\endgroup$ – Simon O'Doherty Oct 17 '15 at 17:30
  • $\begingroup$ @SimonO'Doherty See updated answer. $\endgroup$ – user31159 Oct 17 '15 at 17:38
  • $\begingroup$ perfect! :) Thanks. $\endgroup$ – Simon O'Doherty Oct 17 '15 at 17:38
7
$\begingroup$

The question is answered, but... one can also use a dataset to retrieve the information

{
 {"name" -> "bob", "age" -> "20", "phone" -> "123456"},
 {"name" -> "Fred", "age" -> "40", "phone" -> "098765"}
} 

then

ds = Dataset@(Association /@ input)

Retrieve information:

Select[ds, #name == "Fred" &]

result:

enter image description here

$\endgroup$
4
  • $\begingroup$ I was hoping someone would post an Association answer. This is in my opinion the most natural way to do this sort of thing. $\endgroup$ – march Oct 17 '15 at 20:33
  • $\begingroup$ I've only recently started using associations, but I have been very impressed with its utility as a data structure. $\endgroup$ – J. M.'s torpor Oct 17 '15 at 20:56
  • 1
    $\begingroup$ Or ds[Select[#name == "Fred" &]]. $\endgroup$ – Karsten 7. Oct 17 '15 at 21:49
  • $\begingroup$ @Karsten7.: Indeed, this (your comment) is the way I use the Select command most offen ;-) $\endgroup$ – mgamer Oct 18 '15 at 9:06
4
$\begingroup$

This is a very natural solution that works in all versions of Mathematica:

x = {{"name" -> "bob", "age" -> "20", "phone" -> "123456"}, {"name" -> "Fred", "age" -> "40", "phone" -> "098765"}};

y = ("name" /. #) -> # & /@ x;

"Fred" /. y
(* Out: {"name" -> "Fred", "age" -> "40", "phone" -> "098765"} *)
$\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.