Search a list of records: Difference between revisions

 
(28 intermediate revisions by 17 users not shown)
Line 16:
The data structure to be used contains the names and populations (in millions) of the 10 largest metropolitan areas in Africa, and looks as follows when represented in JSON:
 
<syntaxhighlight lang="javascript">[
<lang JavaScript>[
{ "name": "Lagos", "population": 21.0 },
{ "name": "Cairo", "population": 15.2 },
Line 27:
{ "name": "Abidjan", "population": 4.4 },
{ "name": "Casablanca", "population": 3.98 }
]</langsyntaxhighlight>
 
However, you shouldn't parse it from JSON, but rather represent it natively in your programming language.
Line 69:
 
<hr>
 
=={{header|11l}}==
<syntaxhighlight lang="11l">T City
String name
Float population
 
F (name, population)
.name = name
.population = population
 
V cities = [
City(‘Lagos’, 21),
City(‘Cairo’, 15.2),
City(‘Kinshasa-Brazzaville’, 11.3),
City(‘Greater Johannesburg’, 7.55),
City(‘Mogadishu’, 5.85),
City(‘Khartoum-Omdurman’, 4.98),
City(‘Dar Es Salaam’, 4.7),
City(‘Alexandria’, 4.58),
City(‘Abidjan’, 4.4),
City(‘Casablanca’, 3.98)
]
 
F first_index(cities, condition)
L(city) cities
I condition(city)
R L.index
 
F first(cities, condition)
L(city) cities
I condition(city)
R city
 
print(first_index(cities, city -> city.name == ‘Dar Es Salaam’))
print(first(cities, city -> city.population < 5.0).name)
print(first(cities, city -> city.name[0] == ‘A’).population)</syntaxhighlight>
 
{{out}}
<pre>
6
Khartoum-Omdurman
4.58
</pre>
 
=={{header|8086 Assembly}}==
===Task-Specific Solution===
This solution answers the questions as asked, and only those asked - it won't answer an arbitrary question regarding the list. All I/O subroutines that involve printing the results were left unimplemented to keep this entry brief.
 
<syntaxhighlight lang="asm"> .model small
.stack 1024
.data
Africa WORD LAGOS ;"jagged" arrays are the bane of assembly programming, so store the string's pointer here instead.
WORD 2100H ;this is a bit cheaty but it's easier to store these as BCD whole numbers
WORD CAIRO
WORD 1520H
WORD KB
WORD 1130H
WORD GJ
WORD 0755H
WORD MOGADISHU
WORD 0585H
WORD KO
WORD 0498H
WORD DES
WORD 0470H
WORD ALEXANDRIA
WORD 0458H
WORD ABIDJAN
WORD 0440H
WORD CASABLANCA
WORD 0398H
LAGOS BYTE "Lagos",0
CAIRO BYTE "Cairo",0
KB BYTE "Kinshasa-Brazzaville",0
GJ BYTE "Greater Johannesburg",0
MOGADISHU BYTE "Mogadishu",0
KO BYTE "Khartoum-Omdurman",0
DES BYTE "Dar Es Salaam",0
ALEXANDRIA BYTE "Alexandria"
ABIDJAN BYTE "Abidjan",0
CASABLANCA BYTE "Casablanca",0
.code
start:
 
mov ax,@data
mov ds,ax
mov ax,@code
mov es,ax
cld ;String functions are set to auto-increment
mov ax,2 ;clear screen by reloading the video mode we're in
int 10h
mov si,offset Africa
;test 1: find the index of the city whose name is Dar-Es-Salaam
mov di,offset DES ;it's easier to test the equality of two pointers than of two strings.
mov cx,10 ;ten cities to check
mov bx,0 ;our counter
test_case_1:
lodsw
cmp ax,di ;compare to the pointer of Dar-Es_Salaam
je done_test_case_1
add si,2 ;we know populations aren't going to match so skip them
inc bx ;increment the counter
loop test_case_1
done_test_case_1:
mov al,bl
call Printhex ;print the index of Dar-Es-Salaam
call Newline ;print CRLF
 
;test 2: print the name of the first city whose population is less than 5 million.
mov si,offset Africa
mov cx,10
test_case_2:
lodsw ;we know that the struct goes city:pop so skip the first word.
lodsw
cmp ax,0500h
jae skip
sub si,4 ;point SI back to the city name
mov si,[ds:si]
call PrintString
call NewLine
jmp done_test_case_2
skip:
loop test_case_2
done_test_case_2:
;test 3: find the population of the first city in this list whose name starts with A
mov si,offset Africa
mov cx,10
test_case_3:
lodsw
push si
mov si,ax
lodsb
cmp al,'A'
pop si
je FoundIt ;popping SI won't affect the compare result.
add si,2 ;skip population
loop test_case_3
 
ExitDOS:
mov ax,4C00h ;return to dos
int 21h
FoundIt:
lodsw
mov dx,ax
mov al,dh
call Printhex_NoLeadingZeroes
mov al,'.' ;we're faking floating point for simplicity's sake
call PrintChar
mov al,dl
call PrintHex
jmp ExitDos
end start</syntaxhighlight>
 
{{out}}
<pre>06
Khartoum-Omdurman
4.58</pre>
 
=={{header|8th}}==
8th uses JSON as its native data representation, so using it is quite natural:
<langsyntaxhighlight lang="forth">[
{ "name": "Lagos", "population": 21.0 },
{ "name": "Cairo", "population": 15.2 },
Line 114 ⟶ 296:
) a:each drop rdrop
 
bye</langsyntaxhighlight>
{{out}}
<pre>
Line 120 ⟶ 302:
The name of the first city in this list whose population is less than 5 million: Khartoum-Omdurman
The population of the first city in this list whose name starts with the letter "A": 4.58000
</pre>
 
=={{header|Action!}}==
{{libheader|Action! Tool Kit}}
<syntaxhighlight lang="action!">INCLUDE "D2:REAL.ACT" ;from the Action! Tool Kit
 
DEFINE PTR="CARD"
DEFINE ENTRY_SIZE="4"
DEFINE STX="$8E"
DEFINE STA="$8D"
DEFINE JSR="$20"
DEFINE RTS="$60"
 
TYPE City=[
CARD
name, ;CHAR ARRAY
population] ;REAL POINTER
 
BYTE ARRAY cities(100)
BYTE count=[0]
 
CHAR ARRAY nameParam ;param for name predicate
REAL popParam ;param for population predicate
CHAR letterParam ;param for letter predicate
CITY POINTER c ;city used in predicates and actions
BYTE index ;index of city used in index action
 
PTR FUNC GetItemAddr(BYTE index)
PTR addr
 
addr=cities+index*ENTRY_SIZE
RETURN (addr)
 
PROC Append(CHAR ARRAY n REAL POINTER p)
City POINTER dst
 
dst=GetItemAddr(count)
dst.name=n
dst.population=p
count==+1
RETURN
 
PROC InitData()
REAL lg,ca,ki,gr,mo,kh,da,al,ab,cs
 
ValR("21.0",lg) ValR("15.2",ca)
ValR("11.3",ki) ValR("7.53",gr)
ValR("5.85",mo) ValR("4.98",kh)
ValR("4.7",da) ValR("4.58",al)
ValR("4.4",ab) ValR("3.98",cs)
 
Append("Lagos",lg)
Append("Cairo",ca)
Append("Kinshasa-Brazzaville",ki)
Append("Greater Johannesburg",gr)
Append("Mogadishu",mo)
Append("Khartoum-Omdurman",kh)
Append("Dar Es Salaam",da)
Append("Alexandria",al)
Append("Abidjan",ab)
Append("Casablanca",cs)
RETURN
 
BYTE FUNC NameEquals()
RETURN (SCompare(c.name,nameParam)+1)
 
BYTE FUNC PopulationLess()
REAL diff
BYTE ARRAY x
 
RealSub(popParam,c.population,diff)
x=diff
IF (x(0)&$80)=$00 THEN
RETURN (1)
FI
RETURN (0)
 
BYTE FUNC FirstLetter()
CHAR ARRAY n
 
n=c.name
IF n(0)>=1 AND n(1)=letterParam THEN
RETURN (1)
FI
RETURN (0)
 
;jump addr is stored in X and A registers
BYTE FUNC Predicate=*(PTR jumpAddr)
[STX Predicate+8
STA Predicate+7
JSR $00 $00
RTS]
 
PROC PrintIndex()
PrintF("index=%I%E",index)
RETURN
 
PROC PrintName()
PrintF("name=%S%E",c.name)
RETURN
 
PROC PrintPopulation()
Print("population=")
PrintRE(c.population)
RETURN
 
;jump addr is stored in X and A registers
PROC Action=*(PTR jumpAddr)
[STX Action+8
STA Action+7
JSR $00 $00
RTS]
 
PROC Find(PTR predicateFun,actionFun)
FOR index=0 TO count-1
DO
c=GetItemAddr(index)
IF Predicate(predicateFun) THEN
Action(actionFun)
EXIT
FI
OD
RETURN
 
PROC Main()
Put(125) PutE() ;clear screen
InitData()
 
nameParam="Dar Es Salaam"
Find(NameEquals,PrintIndex)
 
ValR("5.0",popParam)
Find(PopulationLess,PrintName)
 
letterParam='A
Find(FirstLetter,PrintPopulation)
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Search_a_list_of_records.png Screenshot from Atari 8-bit computer]
<pre>
index=6
name=Khartoum-Omdurman
population=4.58
</pre>
 
Line 128 ⟶ 453:
{{works with|Ada|Ada|2005}}
 
<langsyntaxhighlight Adalang="ada">with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO;
 
Line 211 ⟶ 536:
Ada.Text_IO.Put_Line(+Element(Find(cities, Less_Than_Five_Million'Access)).name);
Ada.Text_IO.Put_Line(Element(Find(cities, Starts_With_A'Access)).population'Img);
end Search_A_List_Of_Records;</langsyntaxhighlight>
{{out}}
<pre> 6
Line 219 ⟶ 544:
 
=={{header|ALGOL 68}}==
<langsyntaxhighlight lang="algol68"># Algol 68 doesn't have generic array searches but we can easily provide #
# type specific ones #
 
Line 290 ⟶ 615:
)
)
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 302 ⟶ 627:
{{Trans|JavaScript}}
 
<langsyntaxhighlight AppleScriptlang="applescript">-- RECORDS
 
property lstCities : [¬
Line 384 ⟶ 709:
end script
end if
end mReturn</langsyntaxhighlight>
 
{{Out}}
<langsyntaxhighlight AppleScriptlang="applescript">{6, "Khartoum-Omdurman", 4.58}</langsyntaxhighlight>
 
=== AppleScriptObjectiveC ===
Line 393 ⟶ 718:
While vanilla AppleScript doesn't provide filters for its own lists and records (and, by the way, has never officially supported square-bracket lists like the one used in the script above), its extension AppleScriptObjectiveC ''can'' filter the equivalent Foundation classes. So bridging between the classes may occasionally be useful. For efficiency, one would try to avoid repeatedly bridging the same objects.
 
<langsyntaxhighlight lang="applescript">use AppleScript version "2.4" -- OS X 10.10 (Yosemite) or later
use framework "Foundation"
 
Line 433 ⟶ 758:
return {result1, result2, result3} --> {6, "Khartoum-Omdurman", 4.58}
end run</langsyntaxhighlight>
 
=={{header|Arturo}}==
 
<syntaxhighlight lang="rebol">; by @Krenium
 
define :city [name population][]
 
records: map [
["Lagos" 21.0]
["Cairo" 15.2]
["Kinshasa-Brazzaville" 11.3]
["Greater Johannesburg" 7.55]
["Mogadishu" 5.85]
["Khartoum-Omdurman" 4.98]
["Dar Es Salaam" 4.7]
["Alexandria" 4.58]
["Abidjan" 4.4]
["Casablanca" 3.98]
] => [to :city &]
 
find: function [block f][
loop.with: 'i block 'elt [
if f elt -> return @[elt i]
]
return false
]
 
; Print the index of the first city named Dar Es Salaam.
print last find records $[c][equal? c\name "Dar Es Salaam"]
 
; Print the name of the first city with under 5 million people.
print get first find records $[c][less? c\population 5] 'name
 
; Print the population of the first city starting with 'A'.
print get first find records $[c][equal? first c\name `A`] 'population</syntaxhighlight>
 
{{out}}
 
<pre>6
Khartoum-Omdurman
4.58</pre>
 
=={{header|BASIC}}==
==={{header|Commodore BASIC}}===
C= BASIC has no associative data structure, so this just uses a two-dimensional array. It is written to accept a dynamically-sized list of cities and populations, with an empty-string sentinel indicating the end of the list.
It also uses a form of pseudo-higher-order programming: the search function uses the query function `FNQ`, which is redefined by the caller to match the desired criteria for each test.
 
Note that in text mode (upper/lowercase), BASIC keywords are only recognized in lowercase.
<syntaxhighlight lang="gwbasic">100 nc=0
110 read n$
120 if n$="" then 160
130 read p$
140 nc=nc+1
150 goto 110
160 restore
170 dim ci$(nc-1,1)
180 for i=0 to nc-1
190 : for j=0 to 1
200 : read ci$(i,j)
210 : next j
220 next i
230 :
240 print chr$(14);:rem text mode
250 print: print "Test 1. name='Dar Es Salaam':"
260 rem search uses query function fnq
270 def fnq(i) = ci$(i,0) = "Dar Es Salaam"
280 gosub 500
290 if i<0 then print " None found.":goto 310
300 print " Index="i"."
310 print: print "Test 2. population < 5M:"
320 def fnq(i) = val(ci$(i,1)) < 5
330 gosub 500
340 if i<0 then print " None found.":goto 360
350 print " Name="ci$(i,0)"."
360 print: print "Test 3. name like 'A%':"
370 def fnq(i) = left$(ci$(i,0),1)="A"
380 gosub 500
390 if i<0 then print " None found.":goto 410
400 print " Population="ci$(i,1)"."
410 end
420 :
500 for i=0 to nc-1
510 : if fnq(i) then return
520 next i
530 i=-1
540 return
550 :
560 data "Lagos", 21.0
570 data "Cairo", 15.2
580 data "Kinshasa-Brazzaville", 11.3
590 data "Greater Johannesburg", 7.55
600 data "Mogadishu", 5.85
610 data "Khartoum-Omdurman", 4.98
620 data "Dar Es Salaam", 4.7
630 data "Alexandria", 4.58
640 data "Abidjan", 4.4
650 data "Casablanca", 3.98
660 data ""</syntaxhighlight>
 
{{Out}}
<pre>ready.
run
 
Test 1. name='Dar Es Salaam':
Index= 6 .
 
Test 2. population < 5M:
Name=Khartoum-Omdurman.
 
Test 3. name like 'A%':
Population=4.58.
 
ready.</pre>
 
==={{header|FreeBASIC}}===
<syntaxhighlight lang="freebasic">Type Registro
name As String*20
population As Double
End Type
Dim cities(1 To 10) As Registro => { _
("Lagos",21.0 ), ("Cairo", 15.2 ), ("Kinshasa-Brazzaville", 11.3 ), _
("Greater Johannesburg", 7.55), ("Mogadishu", 5.85), ("Khartoum-Omdurman", 4.98), _
("Dar Es Salaam", 4.7 ), ("Alexandria", 4.58), ("Abidjan", 4.4 ), ("Casablanca", 3.98)}
 
Dim As Byte n
For n = 1 To Ubound(cities)
If cities(n).name = "Dar Es Salaam" Then Print n-1
Next n
 
For n = 1 To Ubound(cities)
If cities(n).population < 5.00 Then Print cities(n).name : Exit For
Next n
 
For n = 1 To Ubound(cities)
If Left(cities(n).name,1) = "A" Then Print cities(n).population : Exit For
Next n
Sleep</syntaxhighlight>
{{out}}
<pre> 6
Khartoum-Omdurman
4.58</pre>
 
==={{header|QBasic}}===
{{works with|QBasic|1.1}}
{{works with|QuickBasic|4.5}}
<syntaxhighlight lang="qbasic">DIM cities$(10, 10)
cities$(1, 1) = "Lagos": cities$(1, 2) = "21.0"
cities$(2, 1) = "Cairo": cities$(2, 2) = "15.2"
cities$(3, 1) = "Kinshasa-Brazzaville": cities$(3, 2) = "11.3"
cities$(4, 1) = "Greater Johannesburg": cities$(4, 2) = "7.55"
cities$(5, 1) = "Mogadishu": cities$(5, 2) = "5.85"
cities$(6, 1) = "Khartoum-Omdurman": cities$(6, 2) = "4.98"
cities$(7, 1) = "Dar Es Salaam": cities$(7, 2) = "4.7"
cities$(8, 1) = "Alexandria": cities$(8, 2) = "4.58"
cities$(9, 1) = "Abidjan": cities$(9, 2) = "4.4"
cities$(10, 1) = "Casablanca": cities$(10, 2) = "3.98"
 
FOR n = 1 TO UBOUND(cities$)
IF cities$(n, 1) = "Dar Es Salaam" THEN PRINT n - 1
NEXT n
 
FOR n = 1 TO UBOUND(cities$)
IF VAL(cities$(n, 2)) < 5! THEN PRINT cities$(n, 1): EXIT FOR
NEXT n
 
FOR n = 1 TO UBOUND(cities$)
IF LEFT$(cities$(n, 1), 1) = "A" THEN PRINT cities$(n, 2): EXIT FOR
NEXT n
</syntaxhighlight>
{{out}}
<pre>Same as FreeBASIC entry.</pre>
 
==={{header|True BASIC}}===
<syntaxhighlight lang="qbasic">DIM cities$(10, 10)
LET cities$(1, 1) = "Lagos"
LET cities$(1, 2) = "21.0"
LET cities$(2, 1) = "Cairo"
LET cities$(2, 2) = "15.2"
LET cities$(3, 1) = "Kinshasa-Brazzaville"
LET cities$(3, 2) = "11.3"
LET cities$(4, 1) = "Greater Johannesburg"
LET cities$(4, 2) = "7.55"
LET cities$(5, 1) = "Mogadishu"
LET cities$(5, 2) = "5.85"
LET cities$(6, 1) = "Khartoum-Omdurman"
LET cities$(6, 2) = "4.98"
LET cities$(7, 1) = "Dar Es Salaam"
LET cities$(7, 2) = "4.7"
LET cities$(8, 1) = "Alexandria"
LET cities$(8, 2) = "4.58"
LET cities$(9, 1) = "Abidjan"
LET cities$(9, 2) = "4.4"
LET cities$(10, 1) = "Casablanca"
LET cities$(10, 2) = "3.98"
 
FOR n = 1 TO UBOUND(cities$,1)
IF cities$(n, 1) = "Dar Es Salaam" THEN PRINT n-1
NEXT n
 
FOR n = 1 TO UBOUND(cities$,1)
IF VAL(cities$(n, 2)) < 5 THEN
PRINT cities$(n, 1)
EXIT FOR
END IF
NEXT n
 
FOR n = 1 TO UBOUND(cities$,1)
IF (cities$(n, 1))[1:1] = "A" THEN
PRINT cities$(n, 2)
EXIT FOR
END IF
NEXT n
END</syntaxhighlight>
{{out}}
<pre>Same as FreeBASIC entry.</pre>
 
==={{header|Yabasic}}===
<syntaxhighlight lang="yabasic">dim cities$(9, 9)
cities$(0, 0) = "Lagos" : cities$(0, 1) = "21.0"
cities$(1, 0) = "Cairo" : cities$(1, 1) = "15.2"
cities$(2, 0) = "Kinshasa-Brazzaville" : cities$(2, 1) = "11.3"
cities$(3, 0) = "Greater Johannesburg" : cities$(3, 1) = "7.55"
cities$(4, 0) = "Mogadishu" : cities$(4, 1) = "5.85"
cities$(5, 0) = "Khartoum-Omdurman" : cities$(5, 1) = "4.98"
cities$(6, 0) = "Dar Es Salaam" : cities$(6, 1) = "4.7"
cities$(7, 0) = "Alexandria" : cities$(7, 1) = "4.58"
cities$(8, 0) = "Abidjan" : cities$(8, 1) = "4.4"
cities$(9, 0) = "Casablanca" : cities$(9, 1) = "3.98"
 
for n = 1 to arraysize(cities$(), 1)
if cities$(n, 0) = "Dar Es Salaam" print n
next n
 
for n = 1 to arraysize(cities$(), 1)
if val(cities$(n, 1)) < 5 then print cities$(n, 0): break: fi
next n
 
for n = 1 to arraysize(cities$(), 1)
if left$(cities$(n, 0), 1) = "A" then print cities$(n, 1): break: fi
next n</syntaxhighlight>
{{out}}
<pre>Same as FreeBASIC entry.</pre>
 
=={{header|C}}==
 
This solution makes use of the 'bsearch' and 'lfind' library functions. Note: 'lfind' is available only on Posix systems, and is found in the 'search.h' header. However it is also part of the Ming C Compiler for Windows.
<syntaxhighlight lang="c">
<lang c>
#include <stdint.h> /* intptr_t */
#include <stdio.h>
Line 544 ⟶ 1,111:
return 0;
}
</syntaxhighlight>
</lang>
 
Output
Line 554 ⟶ 1,121:
 
=={{header|C sharp|C#}}==
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
 
Line 589 ⟶ 1,156:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 601 ⟶ 1,168:
<tt>std::find_if</tt> accepts a lambda as predicate.
 
<langsyntaxhighlight lang="cpp">#include <iostream>
#include <string>
#include <vector>
Line 643 ⟶ 1,210:
std::cout << i3->population << "\n";
}
}</langsyntaxhighlight>
 
{{out}}
Line 656 ⟶ 1,223:
In order to not rely on the input ordering of the data records, this example adds an "idx" value to the records, for purposes of being able to report the answer to the queries which rely on the original ordering. The data records are then re-sorted to be ordered by city name. This helps to make it clear that the query relying on sort-by-population is properly handled in the query itself.
 
<langsyntaxhighlight Clojurelang="clojure">(def records [{:idx 8, :name "Abidjan", :population 4.4}
{:idx 7, :name "Alexandria", :population 4.58}
{:idx 1, :name "Cairo", :population 15.2}
Line 678 ⟶ 1,245:
 
(defn most-populous-city-below-n [recs limit]
(:name (rec-with-max-population-below-n recs limit)))</langsyntaxhighlight>
 
{{out}}
Line 693 ⟶ 1,260:
 
=={{header|Common Lisp}}==
<langsyntaxhighlight lang="lisp">(defstruct city
(name nil :type string)
(population nil :type number))
Line 717 ⟶ 1,284:
(format t "Answer 1: ~A~%" answer1)
(format t "Answer 2: ~A~%" answer2)
(format t "Answer 3: ~A~%" answer3)))</langsyntaxhighlight>
{{out}}
<pre>Answer 1: 6
Line 731 ⟶ 1,298:
 
We demonstrate the '''vector-search''' primitive, which takes as input a vector, and a predicate.
<langsyntaxhighlight lang="scheme">
(require 'struct)
(require 'json)
Line 765 ⟶ 1,332:
(city-pop -666) → (-666 . not-found)
(city-index "alexandra") → #f
</syntaxhighlight>
</lang>
 
=={{header|Elena}}==
ELENA 56.0x :
<langsyntaxhighlight lang="elena">import extensions;
import system'routines;
Line 788 ⟶ 1,355:
};
var index := dataset.selectBy::(r => r.Name).toArray().indexOfElement("Dar Es Salaam");
console.printLine(index);
var name := dataset.filterBy::(c => c.Population < 5.0r).toArray().FirstMember.Name;
console.printLine(name);
var namePopulation := dataset.filterBy::(c => c.Name.startingWith("A")).toArray().FirstMember.Population;
console.printLine(namePopulation)
}</langsyntaxhighlight>
{{out}}
<pre>
Line 805 ⟶ 1,372:
 
=={{header|Elixir}}==
<langsyntaxhighlight lang="elixir">cities = [
[name: "Lagos", population: 21.0 ],
[name: "Cairo", population: 15.2 ],
Line 820 ⟶ 1,387:
IO.puts Enum.find_index(cities, fn city -> city[:name] == "Dar Es Salaam" end)
IO.puts Enum.find(cities, fn city -> city[:population] < 5.0 end)[:name]
IO.puts Enum.find(cities, fn city -> String.first(city[:name])=="A" end)[:population]</langsyntaxhighlight>
 
{{out}}
Line 833 ⟶ 1,400:
 
Not only does <code>find</code> return the element, but also the index, which allows us to use <code>find</code> for all of the required tasks. Since Factor is a stack-based concatenative language, multiple return values are elegant to use. We can simply <code>drop</code> the sequence element on the top of the data stack if we are only interested in the index, or we can <code>nip</code> the index if we are only interested in the sequence element on the top of the stack.
<langsyntaxhighlight lang="factor">USING: accessors io kernel math prettyprint sequences ;
IN: rosetta-code.search-list
 
Line 858 ⟶ 1,425:
 
! Print the population of the first city starting with 'A'.
data [ name>> first CHAR: A = ] find nip pop>> .</langsyntaxhighlight>
{{out}}
<pre>
Line 881 ⟶ 1,448:
Such arrays involve the ability to access an individual city's information at random, simply by specifying the index into the CITY array, however the given problem requires only sequential access. In such a case, the storage for the city elements could be formed as a linked-list which would be followed sequentially. Even so, random access can be regained via an array such as XCNAME, which now would hold the storage address of the corresponding CITY element. And as ever, how long is a piece of string? Here, ten.
 
If the data were stored as records in a disc file, a record zero won't exist and so appropriate testing for "not found" will be required. For this example however there is no attempt either to prepare a suitable "not found" entry nor to test and evade such a misfortune. The test data employed do not provoke such errors... <langsyntaxhighlight Fortranlang="fortran"> MODULE SEMPERNOVIS !Keep it together.
TYPE CITYSTAT !Define a compound data type.
CHARACTER*28 NAME !Long enough?
Line 931 ⟶ 1,498:
WRITE (6,3) BLAH,CITY(FIRSTMATCH(CITY.NAME(1:1),"A")).POPULATION
3 FORMAT (A,"whose name starts with A has population",F5.2)
END</langsyntaxhighlight>
 
The words NAME and TARGET can have special usages in F90, but fortran has ''no'' reserved words so these names can be put to ordinary use. Alas, the syntax highlighter does not recognise their non-special use and gives them colour. One could fuss further over the layout of the output, but here it is:
Line 942 ⟶ 1,509:
=={{header|Go}}==
'''Basic solution:'''
<langsyntaxhighlight lang="go">package main
 
import (
Line 998 ⟶ 1,565:
fmt.Println(list[i].population)
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 1,011 ⟶ 1,578:
 
First, a package to define the data structure needed. This package will be imported by both the data conversion tool and the application.
<langsyntaxhighlight lang="go">package datadef
 
type Element struct {
Line 1,018 ⟶ 1,585:
}
 
type List []Element</langsyntaxhighlight>
 
Then the data conversion tool. This program reads JSON from stdin and generates the Go code of a package "data" containing an equivalent Go literal.
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,053 ⟶ 1,620:
}
fmt.Fprintln(f, "}")
}</langsyntaxhighlight>
{{out}}
<langsyntaxhighlight lang="go">package data
import "datadef"
Line 1,070 ⟶ 1,637:
8: {"Abidjan", 4.4},
9: {"Casablanca", 3.98},
}</langsyntaxhighlight>
 
The desired program imports the generated package containing the converted data. Program and imported data are JSON-free.
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,119 ⟶ 1,686:
fmt.Println(data.List[i].Population)
}
}</langsyntaxhighlight>
Output same as basic solution.
 
Line 1,126 ⟶ 1,693:
The population ordering is useful only for queries against population and so cannot be used, at least not in any simple way, by the general find function shown above. The sort package of the Go standard library however contains a function for making general queries against an ordered list. This solution shows how the population query can be done with this function.
 
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,150 ⟶ 1,717:
fmt.Println(data.List[i].Name)
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 1,160 ⟶ 1,727:
The same sort.Search function is general enough to be used for the other two queries of the task as long as appropriate indexes are constructed. sort.Search is interesting because it is in the standard library and is much like the function required by the task, being generalized to take a function as an argument. It does not completely meet task requirements though because it works on a single ordering that must already exist or already be computed. A function that would analyze a general query, use available orderings when possible, and fall back on linear search otherwise is surely beyond the task scope.
 
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,203 ⟶ 1,770:
fmt.Println(data.List[nx[i]].Population)
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 1,212 ⟶ 1,779:
=={{header|Haskell}}==
 
<langsyntaxhighlight Haskelllang="haskell">import Data.List (findIndex, find)
 
data City = City
Line 1,290 ⟶ 1,857:
=> Maybe a -> IO ()
mbPrint (Just x) = print x
mbPrint x = print x</langsyntaxhighlight>
 
{{Out}}
Line 1,301 ⟶ 1,868:
To represent the data in the task description, we will be using a tabular format as follows:
 
<langsyntaxhighlight Jlang="j">colnumeric=: 0&".&.>@{`[`]}
 
data=: 1 colnumeric |: fixcsv 0 :0
Line 1,314 ⟶ 1,881:
Abidjan, 4.4
Casablanca, 3.98
)</langsyntaxhighlight>
 
And here are the required computations:
 
<langsyntaxhighlight Jlang="j"> (0 { data) i. <'Dar Es Salaam'
6
(i. >./)@(* 5&>)@:>@{: data
Line 1,325 ⟶ 1,892:
Khartoum-Omdurman
(1 { data) {::~ 'A' i.~ {.&> 0 { data
4.58</langsyntaxhighlight>
 
The "general search function" mentioned in the task does not seem a natural fit for this set of data, because of the multi-column nature of this data. Nevertheless, we could for example define:
 
<langsyntaxhighlight lang="j">gsf=: 1 :0
:
I. u x { y
)</langsyntaxhighlight>
 
This uses the single argument aspect of the definition of <code>I.</code> to convert a bit mask to the corresponding sequence of indices. And the column(s) we are searching on are exposed as a parameter for the interface, which allows us to ignore (for this problem) the irrelevant columns...
Line 1,338 ⟶ 1,905:
Thus, we could say:
 
<langsyntaxhighlight Jlang="j"> 1 (= >./)@(* 5&>)@:> gsf data
5</langsyntaxhighlight>
 
But this doesn't seem any clearer or more concise than our previous expression which finds the index of the first example of the most populous city with a population less than five million. Not only that, but if there were multiple cities which had the same population number which satisfied this constraint, this version would return all of those indices where the task explicitly required we return the first example.
Line 1,345 ⟶ 1,912:
=== J: Another approach ===
The following approach is arguably more natural in J than requiring a dictionary-type structure.
<langsyntaxhighlight lang="j"> city=: <;._1 ';Lagos;Cairo;Kinshasa-Brazzaville;Greater Johannesburg;Mogadishu;Khartoum-Omdurman;Dar Es Salaam;Alexandria;Abidjan;Casablanca'
popln=: 21 15.2 11.3 7.55 5.85 4.98 4.7 4.58 4.4 3.98
city i. <'Dar Es Salaam' NB. index of Dar Es Salaam
Line 1,358 ⟶ 1,925:
4.58
(popln {~ ({.&> city)&i.) 'A' NB. anonymous search function with first letter as argument
4.58</langsyntaxhighlight>
 
=={{header|Java}}==
Line 1,370 ⟶ 1,937:
{{works with|Java|8}}
 
<langsyntaxhighlight Javalang="java">import java.util.Arrays;
import java.util.Collections;
import java.util.List;
Line 1,498 ⟶ 2,065:
}
}
</syntaxhighlight>
</lang>
 
{{Out}}
Line 1,509 ⟶ 2,076:
===ES5===
 
<langsyntaxhighlight JavaScriptlang="javascript">(function () {
'use strict';
Line 1,558 ⟶ 2,125:
};
})();</langsyntaxhighlight>
 
 
Line 1,566 ⟶ 2,133:
===ES6===
 
<langsyntaxhighlight JavaScriptlang="javascript">(() => {
'use strict';
Line 1,590 ⟶ 2,157:
};
})();</langsyntaxhighlight>
 
 
Line 1,600 ⟶ 2,167:
"jq" is so-name because it is a JSON Query Language, and thus all the abstractions are already available for the given searches, except that early versions of jq do not have `first/1` as a builtin. If your jq does not define `first/1`, then for present purposes, an appropriate definition would be:
 
<langsyntaxhighlight lang="jq">def first(s): [s][0];</langsyntaxhighlight>
 
This will emit `null` if the stream, s, is empty.
Line 1,629 ⟶ 2,196:
{{works with|Julia|0.6}}
 
<langsyntaxhighlight lang="julia">using DataFrames
 
dataset = DataFrame(name=["Lagos", "Cairo", "Kinshasa-Brazzaville", "Greater Johannesburg", "Mogadishu",
Line 1,640 ⟶ 2,207:
println(dataset[first(find(dataset[:population] .< 5)), :name])
print("Find the population of the first city in this list whose name starts with the letter \"A\": ")
println(dataset[first(find(startswith.(dataset[:name], 'A'))), :population])</langsyntaxhighlight>
 
{{out}}
Line 1,648 ⟶ 2,215:
 
=={{header|Kotlin}}==
<langsyntaxhighlight lang="scala">// version 1.1.2
 
class City(val name: String, val pop: Double)
Line 1,672 ⟶ 2,239:
val pop = cities.first { it.name[0] == 'A' }.pop
println("Population of first city whose name starts with 'A' = $pop")
}</langsyntaxhighlight>
 
{{out}}
Line 1,682 ⟶ 2,249:
 
=={{header|Lingo}}==
<langsyntaxhighlight lang="lingo">on findFirstRecord (data, condition)
cnt = data.count
repeat with i = 1 to cnt
Line 1,688 ⟶ 2,255:
if value(condition) then return [#index:i-1, #record:record]
end repeat
end</langsyntaxhighlight>
 
<langsyntaxhighlight lang="lingo">data = [\
[ "name": "Lagos", "population": 21.0 ],\
[ "name": "Cairo", "population": 15.2 ],\
Line 1,718 ⟶ 2,285:
res = findFirstRecord(data, "record.name.char[1]="&q&"A"&q)
if listP(res) then put res.record.population
-- 4.5800</langsyntaxhighlight>
 
=={{header|Lua}}==
Lua tables are well suited as the element type for this task. The master data structure is a table of tables.
<langsyntaxhighlight Lualang="lua">-- Dataset declaration
local cityPops = {
{name = "Lagos", population = 21.0},
Line 1,752 ⟶ 2,319:
function (i, e) if e.name:sub(1, 1) == "A" then return e.population end end
}
for _, func in pairs(testCases) do print(recordSearch(cityPops, func)) end</langsyntaxhighlight>
{{out}}
<pre>6
Khartoum-Omdurman
4.58</pre>
 
=={{header|Ksh}}==
<syntaxhighlight lang="ksh">
#!/bin/ksh
 
# Search a list of records
 
# # Variables:
#
json='{ "name": "Lagos", "population": 21.0 },
{ "name": "Cairo", "population": 15.2 },
{ "name": "Kinshasa-Brazzaville", "population": 11.3 },
{ "name": "Greater Johannesburg", "population": 7.55 },
{ "name": "Mogadishu", "population": 5.85 },
{ "name": "Khartoum-Omdurman", "population": 4.98 },
{ "name": "Dar Es Salaam", "population": 4.7 },
{ "name": "Alexandria", "population": 4.58 },
{ "name": "Abidjan", "population": 4.4 },
{ "name": "Casablanca", "population": 3.98 }'
 
typeset -a African_Metro
integer i=0
 
typeset -T Metro_Africa_t=(
typeset -h 'Metro name' met_name=''
typeset -E3 -h 'Metro population' met_pop
 
function init_metro {
typeset name ; name="$1"
typeset pop ; typeset -E3 pop=$2
 
_.met_name=${name}
_.met_pop=${pop}
}
 
function prt_name {
print "${_.met_name}"
}
 
function prt_pop {
print "${_.met_pop}"
}
)
 
# # Functions:
#
 
# # Function _findcityindex(arr, name) - return array index of citry named "name"
#
function _findcityindex {
typeset _arr ; nameref _arr="$1"
typeset _name ; _name="$2"
typeset _i ; integer _i
 
for ((_i=0; _i<${#_arr[*]}; _i++)); do
[[ ${_name} == $(_arr[_i].prt_name) ]] && echo ${_i} && return 0
done
echo "-1"
return 1
}
 
# # Function _findcitynamepop(arr, pop, xx) - find 1st city name pop $3 of $2
#
function _findcitynamepop {
typeset _arr ; nameref _arr="$1"
typeset _pop ; typeset -E3 _pop=$2
typeset _comp ; _comp="$3"
typeset _i ; integer _i
 
for ((_i=0; _i<${#_arr[*]}; _i++)); do
case ${_comp} in
gt)
[[ $(_arr[_i].prt_pop) -gt ${_pop} ]] && _arr[_i].prt_name && return 0 ;;
lt)
[[ $(_arr[_i].prt_pop) -lt ${_pop} ]] && _arr[_i].prt_name && return 0 ;;
esac
done
echo "DNE"
return 1
}
 
# # Function _findcitypopname(arr, pat) - find pop of first city starting w/ pat
#
function _findcitypopname {
typeset _arr ; nameref _arr="$1"
typeset _pat ; _pat="$2"
typeset _i ; integer _i
 
for ((_i=0; _i<${#_arr[*]}; _i++)); do
[[ $(_arr[_i].prt_name) == ${_pat}* ]] && _arr[_i].prt_pop && return 0
done
echo "-1"
return 1
}
 
######
# main #
######
 
# # An indexed array of Type variable (objects)
#
echo "${json}" | while read; do
metro="${REPLY#*\"name\"\:\ }" ; metro="${metro%%\,*}" ; metro="${metro//\"/}"
population="${REPLY#*\"population\"\:\ }" ; population=${population%+(\ )\}*(\,)}
 
Metro_Africa_t African_Metro[i]
African_Metro[i++].init_metro "${metro}" ${population}
done
 
_findcityindex African_Metro "Dar Es Salaam"
_findcitynamepop African_Metro 5.0 lt
_findcitypopname African_Metro "A"</syntaxhighlight>
{{out}}<pre>
6
Khartoum-Omdurman
4.58</pre>
 
=={{header|Maple}}==
<langsyntaxhighlight Maplelang="maple">rec := [table(["name"="Lagos","population"=21.0]),
table(["name"="Cairo","population"=15.2]),
table(["name"="Kinshasa-Brazzaville","population"=11.3]),
Line 1,780 ⟶ 2,466:
searchRec(rec, x->x["name"] = "Dar Es Salaam", (x,i)->print(i-1)): # minus 1 since Maple is 1-indexed
searchRec(rec, x->x["population"]<5, (x,i)->print(x["name"])):
searchRec(rec, x->x["name"][1] = "A", (x,i)->print(x["population"])):</langsyntaxhighlight>
{{out}}
<pre> 6
Line 1,787 ⟶ 2,473:
</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">data = Dataset[{
<lang Mathematica>
data = Dataset[{
<|"name" -> "Lagos", "population" -> 21.|>,
<|"name" -> "Cairo", "population" -> 15.2|>,
Line 1,801 ⟶ 2,486:
<|"name" -> "Casablanca", "population" -> 3.98|>
}]
 
data[Position["Dar Es Salaam"], "name"][1, 1] - 1
 
data[Select[#population < 5 &]][1, "name"]
data[Select[StringMatchQ[#name, "A*"] &]][1, "population"]</syntaxhighlight>
 
=={{header|Nim}}==
data[Select[StringMatchQ[#name, "A*"] &]][1, "population"]</lang>
To solve this task, we define a template “findIt” similar to the templates provided by the standard library module “sequtils”. As First argument it accepts any collection providing a “pairs” iterator (yielding an index and a value), for instance a sequence (list) or a table (hash). The second argument of the template is a predicate, i.e. an expression containing the “it” variable.
 
This way, the template is able to work in a lot of contexts.
 
<syntaxhighlight lang="nim">template findIt(data, pred: untyped): int =
## Return the index of the first element in "data" satisfying
## the predicate "pred" or -1 if no such element is found.
var result = -1
for i, it {.inject.} in data.pairs:
if pred:
result = i
break
result
 
 
when isMainModule:
 
import strutils
 
type City = tuple[name: string; population: float]
 
const Cities: seq[City] = @[("Lagos", 21.0),
("Cairo", 15.2),
("Kinshasa-Brazzaville", 11.3),
("Greater Johannesburg", 7.55),
("Mogadishu", 5.85),
("Khartoum-Omdurman", 4.98),
("Dar Es Salaam", 4.7),
("Alexandria", 4.58),
("Abidjan", 4.4),
("Casablanca", 3.98)]
 
echo "Index of the first city whose name is “Dar Es Salaam”: ",
Cities.findIt(it.name == "Dar Es Salaam")
 
let idx1 = Cities.findIt(it.population < 5)
echo "Name of the first city whose population is less than 5 million: ",
if idx1 == -1: "<none>" else: Cities[idx1].name
 
let idx2 = Cities.findIt(it.name.startsWith("A"))
echo "Population of the first city whose name starts with the letter “A”: ",
if idx2 == -1: "<none>" else: $Cities[idx2].population</syntaxhighlight>
 
{{out}}
<pre>Index of the first city whose name is “Dar Es Salaam”: 6
Name of the first city whose population is less than 5 million: Khartoum-Omdurman
Population of the first city whose name starts with the letter “A”: 4.58</pre>
 
=={{header|OCaml}}==
{{works with|OCaml|4.03+}}
<langsyntaxhighlight lang="ocaml">
#load "str.cma"
 
Line 1,870 ⟶ 2,601:
|> print_float
|> print_newline;
</syntaxhighlight>
</lang>
{{out}}
6
Khartoum-Omdurman
4.58
=={{header|Pascal}}==
==={{header|Free Pascal}}===
<syntaxhighlight lang="pascal">
program Search_list_records;
{$mode ObjFPC}{$H+}
 
type
TCity = record
name: string;
population: real;
end;
 
const
Cities: array of TCity = (
(name: 'Lagos'; population: 21.0),
(name: 'Cairo'; population: 15.2),
(name: 'Kinshasa-Brazzaville'; population: 11.3),
(name: 'Greater Johannesburg'; population: 7.55),
(name: 'Mogadishu'; population: 5.85),
(name: 'Khartoum-Omdurman'; population: 4.98),
(name: 'Dar Es Salaam'; population: 4.7),
(name: 'Alexandria'; population: 4.58),
(name: 'Abidjan'; population: 4.4),
(name: 'Casablanca'; population: 3.98)
);
 
function FindCityIndex(const CityName: string): Integer;
var
i: Integer;
begin
Result := -1;
for i := 0 to High(Cities) do
if Cities[i].name = CityName then
Exit(i);
end;
 
function FindCityName(const pop: real): string;
var
City: TCity;
begin
Result := 'not found';
for City in Cities do
if City.population < pop then
Exit(City.name);
end;
 
function FindCityPopulation(const Start: Char): Real;
var
City: TCity;
begin
Result := -1;
for City in Cities do
if City.name[1] = Start then
Exit(City.population);
end;
 
begin
writeln('index: ', FindCityIndex('Dar Es Salaam'));
writeln('name: ', FindCityName(5.0));
writeln('population: ', FindCityPopulation('A'):4:2);
end.
 
</syntaxhighlight>
{{out}}
<pre>
index: 6
name: Khartoum-Omdurman
population: 4.58
</pre>
 
=={{header|Perl}}==
Line 1,880 ⟶ 2,680:
The <tt>first</tt> function from the core module <tt>List::Util</tt> provides short-circuiting search using a block as predicate. However, it can only return the value of the found element, not its index &ndash; so for the first test-case we need to operate on the list of indices.
 
<langsyntaxhighlight lang="perl">use feature 'say';
use List::Util qw(first);
 
Line 1,903 ⟶ 2,703:
 
my $record3 = first { $_->{name} =~ /^A/ } @cities;
say $record3->{population};</langsyntaxhighlight>
 
{{out}}
Line 1,914 ⟶ 2,714:
The CPAN module <tt>List::MoreUtils</tt> provides the <tt>first_index</tt> function which could be used to write that first case more elegantly:
 
<langsyntaxhighlight lang="perl">use List::MoreUtils qw(first_index);
 
$index1 = first_index { $_->{name} eq 'Dar Es Salaam' } @cities;</langsyntaxhighlight>
 
=={{header|Phix}}==
{{libheader|Phix/basics}}
<lang Phix>constant CITY_NAME = 1, POPULATION = 2
<!--<syntaxhighlight lang="phix">-->
constant municipalities = {{"Lagos",21},
<span style="color: #008080;">constant</span> <span style="color: #000000;">CITY_NAME</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">POPULATION</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span>
{"Cairo",15.2},
<span style="color: #008080;">constant</span> <span style="color: #000000;">municipalities</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #008000;">"Lagos"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">21</span><span style="color: #0000FF;">},</span>
{"Kinshasa-Brazzaville",11.3},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Cairo"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">15.2</span><span style="color: #0000FF;">},</span>
{"Greater Johannesburg",7.55},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Kinshasa-Brazzaville"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">11.3</span><span style="color: #0000FF;">},</span>
{"Mogadishu",5.85},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Greater Johannesburg"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7.55</span><span style="color: #0000FF;">},</span>
{"Khartoum-Omdurman",4.98},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Mogadishu"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5.85</span><span style="color: #0000FF;">},</span>
{"Dar Es Salaam",4.7},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Khartoum-Omdurman"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4.98</span><span style="color: #0000FF;">},</span>
{"Alexandria",4.58},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Dar Es Salaam"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4.7</span><span style="color: #0000FF;">},</span>
{"Abidjan",4.4},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Alexandria"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4.58</span><span style="color: #0000FF;">},</span>
{"Casablanca",3.98}}
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Abidjan"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4.4</span><span style="color: #0000FF;">},</span>
 
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Casablanca"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3.98</span><span style="color: #0000FF;">}}</span>
function searchfor(sequence s, integer rid, object user_data, integer return_index=0)
for i=1 to length(s) do
<span style="color: #008080;">function</span> <span style="color: #000000;">searchfor</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">rid</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">object</span> <span style="color: #000000;">user_data</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">bool</span> <span style="color: #000000;">return_index</span><span style="color: #0000FF;">=</span><span style="color: #004600;">false</span><span style="color: #0000FF;">)</span>
if call_func(rid,{s[i],user_data}) then
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
return iff(return_index?i:s[i])
<span style="color: #008080;">if</span> <span style="color: #000000;">rid</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">user_data</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
end if
<span style="color: #008080;">return</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">return_index</span><span style="color: #0000FF;">?</span><span style="color: #000000;">i</span><span style="color: #0000FF;">:</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
return 0 -- not found
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">0</span> <span style="color: #000080;font-style:italic;">-- not found</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
function city_named(sequence si, string city_name)
return si[CITY_NAME]=city_name
<span style="color: #008080;">function</span> <span style="color: #000000;">city_named</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">si</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">city_name</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">si</span><span style="color: #0000FF;">[</span><span style="color: #000000;">CITY_NAME</span><span style="color: #0000FF;">]==</span><span style="color: #000000;">city_name</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
?searchfor(municipalities,routine_id("city_named"),"Dar Es Salaam",1)
 
<span style="color: #0000FF;">?</span><span style="color: #000000;">searchfor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">municipalities</span><span style="color: #0000FF;">,</span><span style="color: #000000;">city_named</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Dar Es Salaam"</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">)</span>
function smaller_than(sequence si, atom population)
return si[POPULATION]<population
<span style="color: #008080;">function</span> <span style="color: #000000;">smaller_than</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">si</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">population</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">si</span><span style="color: #0000FF;">[</span><span style="color: #000000;">POPULATION</span><span style="color: #0000FF;">]<</span><span style="color: #000000;">population</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
?searchfor(municipalities,routine_id("smaller_than"),5)[CITY_NAME]
 
<span style="color: #0000FF;">?</span><span style="color: #000000;">searchfor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">municipalities</span><span style="color: #0000FF;">,</span><span style="color: #000000;">smaller_than</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">)[</span><span style="color: #000000;">CITY_NAME</span><span style="color: #0000FF;">]</span>
function starts_with(sequence si, integer ch)
return si[CITY_NAME][1]=ch
<span style="color: #008080;">function</span> <span style="color: #000000;">starts_with</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">si</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">si</span><span style="color: #0000FF;">[</span><span style="color: #000000;">CITY_NAME</span><span style="color: #0000FF;">][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">ch</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
?searchfor(municipalities,routine_id("starts_with"),'A')[POPULATION]</lang>
<span style="color: #0000FF;">?</span><span style="color: #000000;">searchfor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">municipalities</span><span style="color: #0000FF;">,</span><span style="color: #000000;">starts_with</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'A'</span><span style="color: #0000FF;">)[</span><span style="color: #000000;">POPULATION</span><span style="color: #0000FF;">]</span>
<!--</syntaxhighlight>-->
The columnize function reorganises hetrogenous data into corresponding homogenous arrays, which can make this sort of thing much simpler,
at least for exact matches.
<lang Phix>constant {cities,populations} = columnize(municipalities)
 
<!--<syntaxhighlight lang="phix">-->
?populations[find("Dar Es Salaam",cities)]</lang>
<span style="color: #008080;">constant</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">cities</span><span style="color: #0000FF;">,</span><span style="color: #000000;">populations</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">columnize</span><span style="color: #0000FF;">(</span><span style="color: #000000;">municipalities</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">populations</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Dar Es Salaam"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cities</span><span style="color: #0000FF;">)]</span>
<!--</syntaxhighlight>-->
 
{{out}}
<pre>
Line 1,970 ⟶ 2,777:
</pre>
Note that Phix subscripts are 1-based, hence the output of 7 not 6.
 
=={{header|Phixmonti}}==
<syntaxhighlight lang="Phixmonti">include ..\Utilitys.pmt
 
(
( "Lagos" 21.0 )
( "Cairo" 15.2 )
( "Kinshasa-Brazzaville" 11.3 )
( "Greater Johannesburg" 7.55 )
( "Mogadishu" 5.85 )
( "Khartoum-Omdurman" 4.98 )
( "Dar Es Salaam" 4.7 )
( "Alexandria" 4.58 )
( "Abidjan" 4.4 )
( "Casablanca" 3.98 )
)
 
len for >ps
( tps 1 ) sget "Dar Es Salaam" == if ps> 1 - ? exitfor else cps endif
endfor
 
len for
get 2 get 5 < if 1 get ? drop exitfor else drop endif
endfor
 
len for >ps
( tps 1 1 ) sget 'A' == if ( ps> 2 ) sget ? exitfor else cps endif
endfor</syntaxhighlight>
{{out}}
<pre>6
Khartoum-Omdurman
4.58
 
=== Press any key to exit ===</pre>
 
=={{header|PHP}}==
<syntaxhighlight lang="php">
<lang PHP>
<?php
 
Line 2,027 ⟶ 2,868:
 
Done...
</syntaxhighlight>
</lang>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(scl 2)
 
(de *Data
Line 2,051 ⟶ 2,892:
 
(test 4.58
(cadr (find '((L) (pre? "A" (car L))) *Data)) )</langsyntaxhighlight>
 
=={{header|PowerShell}}==
The <code>ConvertFrom-Json</code> cmdlet converts a JSON formatted string to a custom PSCustomObject object that has a property for each field in the JSON string:
<syntaxhighlight lang="powershell">
<lang PowerShell>
$jsonData = @'
[
Line 2,072 ⟶ 2,913:
 
$cities = $jsonData | ConvertFrom-JSON
</syntaxhighlight>
</lang>
The <code>$cities</code> variable contains an array of objects with '''Name''' and '''Population''' properties:
<syntaxhighlight lang="powershell">
<lang PowerShell>
$cities
</syntaxhighlight>
</lang>
{{Out}}
<pre>
Line 2,093 ⟶ 2,934:
</pre>
Find the index of the first city in the list whose name is "Dar Es Salaam":
<syntaxhighlight lang="powershell">
<lang PowerShell>
$cities.Name.IndexOf("Dar Es Salaam")
</syntaxhighlight>
</lang>
{{Out}}
<pre>
Line 2,101 ⟶ 2,942:
</pre>
Find the name of the first city in this list whose population is less than 5 million:
<syntaxhighlight lang="powershell">
<lang PowerShell>
($cities | Where-Object -Property Population -LT 5)[0].Name
</syntaxhighlight>
</lang>
{{Out}}
<pre>
Line 2,109 ⟶ 2,950:
</pre>
Find the population of the first city in this list whose name starts with the letter "A":
<syntaxhighlight lang="powershell">
<lang PowerShell>
($cities | Where-Object -Property Name -Match "^A")[0].Population
</syntaxhighlight>
</lang>
{{Out}}
<pre>
Line 2,119 ⟶ 2,960:
=={{header|Python}}==
 
<langsyntaxhighlight Pythonlang="python">cities = [
{ "name": "Lagos", "population": 21.0 },
{ "name": "Cairo", "population": 15.2 },
Line 2,140 ⟶ 2,981:
first(city['name'] for city in cities if city['population'] < 5),
first(city['population'] for city in cities if city['name'][0] == 'A'),
sep='\n')</langsyntaxhighlight>
 
{{out}}
Line 2,152 ⟶ 2,993:
 
The more idiomatic functions for the task is <code>findf</code> but it doesn't provide the position of the element in the list, so we write a variant. If the item is not found we return <code>#f</code> as most of the Racket primitives do in these cases.
<syntaxhighlight lang="racket">
<lang Racket>
#lang racket
 
Line 2,161 ⟶ 3,002:
[(proc (car lst)) pos]
[else (loop (cdr lst) (add1 pos))])))
</syntaxhighlight>
</lang>
Now we define the list that has the data for the task.
<syntaxhighlight lang="racket">
<lang Racket>
(define data '(#hash((name . "Lagos") (population . 21))
#hash((name . "Cairo") (population . 15.2))
Line 2,174 ⟶ 3,015:
#hash((name . "Abidjan") (population . 4.4))
#hash((name . "Casablanca") (population . 3.98))))
</syntaxhighlight>
</lang>
We write tiny wrappers to retrieve values from the hash.
<syntaxhighlight lang="racket">
<lang Racket>
(define get-name
(lambda (x) (hash-ref x 'name)))
Line 2,182 ⟶ 3,023:
(define get-population
(lambda (x) (hash-ref x 'population)))
</syntaxhighlight>
</lang>
For completeness, ensure the data is sorted by population largest to smallest.
<syntaxhighlight lang="racket">
<lang Racket>
(define sorted-data (sort data > #:key get-population))
</syntaxhighlight>
</lang>
Use an unnamed function with our findf/pos function to get the position of "Dar Es Salaam".
<syntaxhighlight lang="racket">
<lang Racket>
(findf/pos (lambda (x) (equal? "Dar Es Salaam" (get-name x))) sorted-data)
;; -> 6
</syntaxhighlight>
</lang>
Use unnamed functions with findf for the other two test cases.
<syntaxhighlight lang="racket">
<lang Racket>
(get-name (findf (lambda (x) (< (get-population x) 5)) sorted-data))
;; -> "Khartoum-Omdurman"
(get-population (findf (lambda (x) (regexp-match? #rx"^A" (get-name x))) sorted-data))
;; -> 4.58
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 2,213 ⟶ 3,054:
 
{{Works with|Rakudo|2016.08}}
<syntaxhighlight lang="raku" perl6line>my @cities =
{ name => 'Lagos', population => 21.0 },
{ name => 'Cairo', population => 15.2 },
Line 2,228 ⟶ 3,069:
say @cities.first(*<name> eq 'Dar Es Salaam', :k);
say @cities.first(*<population> < 5).<name>;
say @cities.first(*<name>.match: /^A/).<population>;</langsyntaxhighlight>
 
{{out}}
Line 2,252 ⟶ 3,093:
 
This REXX version does &nbsp; ''not'' &nbsp; rely on the list being sorted by population count.
<langsyntaxhighlight lang="rexx">/*REXX program (when using criteria) locates values (indices) from an associate array. */
$="Lagos=21, Cairo=15.2, Kinshasa-Brazzaville=11.3, Greater Johannesburg=7.55, Mogadishu=5.85,",
"Khartoum-Omdurman=4.98, Dar Es Salaam=4.7, Alexandria=4.58, Abidjan=4.4, Casablanca=3.98"
Line 2,269 ⟶ 3,110:
say /*▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ task 3: show 1st city with A* name.*/
c1= 'A' /*1st character of a city for search*/
say '1st city that starts with the letter' c1 "is: " @.c1 /*stick a fork in it, all done*/</langsyntaxhighlight>
'''output''' &nbsp; when using the default inputs:
<pre>
Line 2,280 ⟶ 3,121:
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
# Project : Search a list of records
 
Line 2,313 ⟶ 3,154:
ok
next
</syntaxhighlight>
</lang>
Output:
<pre>
Line 2,323 ⟶ 3,164:
=={{header|Ruby}}==
 
<langsyntaxhighlight Rubylang="ruby">cities = [
{name: "Lagos", population: 21},
{name: "Cairo", population: 15.2},
Line 2,339 ⟶ 3,180:
puts cities.find {|city| city[:population] < 5.0}[:name] # => Khartoum-Omdurman
puts cities.find {|city| city[:name][0] == "A"}[:population] # => 4.58
</syntaxhighlight>
</lang>
 
=={{header|Rust}}==
<langsyntaxhighlight Rustlang="rust">struct City {
name: &'static str,
population: f64,
Line 2,410 ⟶ 3,251:
);
}
</syntaxhighlight>
</lang>
{{Out}}
<pre>Some(6)
Line 2,418 ⟶ 3,259:
=={{header|Scala}}==
{{Out}}See it in running in your browser by [https://scalafiddle.io/sf/8OlRzf8/0 ScalaFiddle (JavaScript executed in browser)] or by [https://scastie.scala-lang.org/fGhNDUNHRqq8h04x3Mm2Kw Scastie (remote JVM)].
<langsyntaxhighlight Scalalang="scala">object SearchListOfRecords extends App {
val cities = Vector(
City("Lagos", 21.0e6),
Line 2,445 ⟶ 3,286:
f"Population of first city whose name starts with 'A' = ${pop.get}%,.0f")
 
}</langsyntaxhighlight>
{{Out}}
<pre>Index of first city whose name is 'Dar Es Salaam' = 6
Line 2,463 ⟶ 3,304:
In a similar way (srfi 132) provides sorting routines with user-defined predicates: one is illustrated to ensure the list of items is sorted in decreasing population order.
 
<langsyntaxhighlight lang="scheme">
(import (scheme base)
(scheme char)
Line 2,517 ⟶ 3,358:
*items*)))
(newline)
</syntaxhighlight>
</lang>
 
{{out}}
Line 2,528 ⟶ 3,369:
=={{header|Sidef}}==
 
<langsyntaxhighlight lang="ruby">struct City {
String name,
Number population,
Line 2,548 ⟶ 3,389:
say cities.index{|city| city.name == "Dar Es Salaam"}
say cities.first{|city| city.population < 5.0}.name
say cities.first{|city| city.name.begins_with("A")}.population</langsyntaxhighlight>
 
{{out}}
Line 2,554 ⟶ 3,395:
6
Khartoum-Omdurman
4.58
</pre>
 
=={{header|SQL}}==
I probably wrote the C implementation for this problem. It has been quite some time, anyways, I got a notification that this page has been edited and while browsing it on my phone I found that this most database worthy of problems doesn't have a SQL implementation. Thus even after a long day, I logged back in again, to rosettacode, not work.
 
I am kind of fond of SQL, I am not a DBA but wanted to be one when I started my career. Databases are among the few things I still hold in respect :)
 
Credits : This wouldn't have been possible without https://sqliteonline.com , you can create your own tables and run queries on them without installing your own DB. The queries below should work on most DBs but some like Access ( is that really a DB ? ) doesn't have LIMIT, or so I read.
 
But to get started, first we create the table :
 
PS : I realised after posting this implementation that not all cities in this list are capitals, well, it was a long day :P
 
<syntaxhighlight lang="sql">
create table african_capitals(name varchar2(100), population_in_millions number(3,2));
</syntaxhighlight>
 
Then we load the data :
 
<syntaxhighlight lang="sql">
insert into african_capitals values("Lagos", 21.0);
insert into african_capitals values("Cairo",15.2);
insert into african_capitals values("Kinshasa-Brazzaville",11.3);
insert into african_capitals values("Greater Johannesburg",7.55);
insert into african_capitals values("Mogadishu",5.85);
insert into african_capitals values("Khartoum-Omdurman",4.98);
insert into african_capitals values("Dar Es Salaam",4.7);
insert into african_capitals values("Alexandria",4.58);
insert into african_capitals values("Abidjan",4.4);
insert into african_capitals values("Casablanca",3.98);
</syntaxhighlight>
 
If you are using sqliteonline.com, run the select query below to inspect your data :
 
<syntaxhighlight lang="sql">
select * from african_capitals;
</syntaxhighlight>
 
Now we are ready to fire the queries to solve the problem statements, one note though : DB tables are 1 indexed, hence the capital of Tanzania is the 7th item, not 6th as is the case for C and it's vast family.
 
<syntaxhighlight lang="sql">
with temp as(select name,row_number() over() as rownum from african_capitals) select rownum from temp where name="Dar Es Salaam";
</syntaxhighlight>
 
{{Output}}
<pre>
7
</pre>
 
The LIMIT keyword in the 2nd and 3rd queries is not supported by all DBs, it works on Oracle and SQLite though
 
<syntaxhighlight lang="sql">
select name from african_capitals where population_in_millions < 5 limit 1;
</syntaxhighlight>
 
{{Output}}
<pre>
Khartoum-Omdurman
</pre>
 
<syntaxhighlight lang="sql">
select population_in_millions from african_capitals where name like "A%" limit 1;
</syntaxhighlight>
 
{{Output}}
<pre>
4.58
</pre>
Line 2,559 ⟶ 3,467:
=={{header|Standard ML}}==
 
<langsyntaxhighlight lang="sml">type city = { name : string, population : real }
 
val citys : city list = [
Line 2,575 ⟶ 3,483:
val firstCityi = #1 (valOf (List.findi (fn (_, city) => #name(city) = "Dar Es Salaam") citys))
val firstBelow5M = #name (valOf (List.find (fn city => #population(city) < 5.0) citys))
val firstPopA = #population (valOf (List.find (fn city => String.substring (#name(city), 0, 1) = "A") citys))</langsyntaxhighlight>
 
{{Output}}
Line 2,586 ⟶ 3,494:
Data:
 
<langsyntaxhighlight lang="swift">struct Place {
var name: String
var population: Double
Line 2,602 ⟶ 3,510:
Place(name: "Abidjan", population: 4.4),
Place(name: "Casablanca", population: 3.98)
]</langsyntaxhighlight>
 
===Using built-in methods===
 
<langsyntaxhighlight lang="swift">guard let salaamI = places.firstIndex(where: { $0.name == "Dar Es Salaam" }) else {
fatalError()
}
Line 2,622 ⟶ 3,530:
}
 
print("Population of first city starting with A: \(startsWithA.population)")</langsyntaxhighlight>
 
{{out}}
Line 2,632 ⟶ 3,540:
===Custom method using Key Paths===
 
<langsyntaxhighlight lang="swift">extension Collection {
func firstIndex<V: Equatable>(
withProperty prop: KeyPath<Element, V>,
Line 2,662 ⟶ 3,570:
}
 
print("Population of first city starting with A: \(places[aI].population)")</langsyntaxhighlight>
 
{{out}}
Line 2,669 ⟶ 3,577:
 
=={{header|Tcl}}==
<langsyntaxhighlight Tcllang="tcl"># records is a list of dicts.
set records {
{ name "Lagos" population 21.0 }
Line 2,704 ⟶ 3,612:
# Find the population of the first city in this list whose name starts with the letter "A"
puts [search $records {[string match A* $name]} {return $population}]
</syntaxhighlight>
</lang>
 
{{out}}
Line 2,710 ⟶ 3,618:
Khartoum-Omdurman
4.58</pre>
 
=={{header|V (Vlang)}}==
<syntaxhighlight lang="Zig">
const cities = {"Lagos": 21.0, "Cairo": 15.2, "Kinshasa-Brazzaville": 11.3, "Greater Johannesburg": 7.55, "Mogadishu": 5.85, "Khartoum-Omdurman": 4.98, "Dar Es Salaam": 4.7, "Alexandria": 4.58, "Abidjan": 4.4, "Casablanca": 3.98}
 
fn main() {
mut count := 0
mut result :=""
for city, population in cities {
count++
if city == "Dar Es Salaam" {
if !result.contains("Index") {result += "Index of '${city}': ${count - 1}\n"}
}
if population < 5 {
if !result.contains("million") {result += "First city with less than 5 million: ${city}\n"}
}
if city[0].ascii_str() == "A" {
if !result.contains("letter") {result += "First population that starts with letter 'A': ${population}\n"}
}
}
println(result.all_before_last("\n"))
}
</syntaxhighlight>
 
{{out}}
<pre>
First city with less than 5 million: Khartoum-Omdurman
Index of 'Dar Es Salaam': 6
First population that starts with letter 'A': 4.58
</pre>
 
=={{header|Wren}}==
{{libheader|Wren-dynamic}}
<syntaxhighlight lang="wren">import "./dynamic" for Tuple
 
var Element = Tuple.create("Element", ["record", "index"])
 
var findFirst = Fn.new { |seq, pred|
var i = 0
for (e in seq) {
if (pred.call(e)) return Element.new(e, i)
i = i + 1
}
return Element.new(null, -1)
}
 
var City = Tuple.create("City", ["name", "pop"])
 
var cities = [
City.new("Lagos", 21.0),
City.new("Cairo", 15.2),
City.new("Kinshasa-Brazzaville", 11.3),
City.new("Greater Johannesburg", 7.55),
City.new("Mogadishu", 5.85),
City.new("Khartoum-Omdurman", 4.98),
City.new("Dar Es Salaam", 4.7),
City.new("Alexandria", 4.58),
City.new("Abidjan", 4.4),
City.new("Casablanca", 3.98)
]
 
var index = findFirst.call(cities) { |c| c.name == "Dar Es Salaam" }.index
System.print("Index of the first city whose name is 'Dar Es Salaam' is %(index).")
var city = findFirst.call(cities) { |c| c.pop < 5 }.record.name
System.print("First city whose population is less than 5 million is %(city).")
var pop = findFirst.call(cities) { |c| c.name[0] == "A" }.record.pop
System.print("The population of the first city whose name begins with 'A' is %(pop).")</syntaxhighlight>
 
{{out}}
<pre>
Index of the first city whose name is 'Dar Es Salaam' is 6.
First city whose population is less than 5 million is Khartoum-Omdurman.
The population of the first city whose name begins with 'A' is 4.58.
</pre>
 
=={{header|zkl}}==
<langsyntaxhighlight lang="zkl">list:=T(SD("name","Lagos", "population",21.0), // SD is a fixed dictionary
SD("name","Cairo", "population",15.2),
SD("name","Kinshasa-Brazzaville", "population",11.3),
Line 2,734 ⟶ 3,716:
// Test case 3:
city:=list.filter1(fcn(city){ city["name"][0]=="A" });
println("The first \"A*\" city (%s) with population under 5 million: %f".fmt(city.values.xplode()));</langsyntaxhighlight>
where a SD is a small read only dictionary and filter1 is a filter that stops at the first match (returning the matched item). The filter method returns False on failure.
The YAJL library could be used to parse the JSON data directly (eg if the data is from the web).
43

edits