4. Arrays

Introduction

Specifying a List In Your Program

a = ("quick", "brown", "fox")
a = "Why are you teasing me?".words
big_array = "mydatafile".open(Sep(crlf)).lines

banner = "The Mines of Moria"
banner = q(The Mines of Moria)

name   = "Gandalf"
banner = "Speak, {name}, and enter!"
banner = qq(Speak, {name}, and welcome!)
ships  = "Niña Pinta Santa María".words # WRONG
ships  = ("Niña", "Pinta", "Santa María")

Printing a List with Commas

commify_series =
    [] -> ""
    l ->
        l', e = l.pop
        l'.join(", ") + " and " + e

array = ("red", "yellow", "green")
println("I have {array.join(" ")} marbles.") #=> I have red yellow green marbles.

Changing Array Size

l.what_about_that_array =
    println("The array now has {l.size} elements.")
    println("The index of the last element is {l.size - 1}.")
    println("Element #3 is `{l[3]}'.")

"Crosby Stills Nash Young".words.what_about_that_array

Doing Something with Every Element in a List

bad_users.each(complain)
bad_users.each(user -> complain(user))

Sys::env.keys.sort.each(var -> "{var}={Sys::env{var}}".println)
Sys::env.each(var, val -> "{var}={val}".println) # but non-sorted
Sys::env.sort_by(a,_ , b,_ -> a <=> b).each(var, val -> "{var}={val}".println)

bad_users.each(user ->
    if user.get_usage > Max_quota then
        complain(user)
)

"who".popen.lines(s ->
    s.m!("tchrist", s.print)
)

df.lines(s ->
    s.words.each(s -> s.rev.println)
)

array.each(item -> "i = {item}".println)
array.each(--)

a = ( 0.5, 3 ); b = ( 0, 1 )
(a,b).each(l ->
    l.map(a ->
        a *= 7
        "{a} ".print
    )
)

Iterating Over an Array by Reference

Extracting Unique Elements from a List

unique = list.uniq

# generate a list of users logged in, removing duplicates
users = "who".popen.lines.map(m(,"(\S+)")).sort.uniq
println("users logged in: {users}")

Finding Elements in One Array but Not Another

difference(a, b)

Computing Union, Intersection, or Difference of Unique Lists

union(a, b)
intersection(a, b)
difference(union(a,b), intersection(a,b))

Appending One Array to Another

members = ("Time", "Flies")
initiates = ("An", "Arrow")
members += initiates
# members is now ("Time", "Flies", "An", "Arrow")

members = ("Time", "Flies")
initiates = ("An", "Arrow")
members.insert!(2, "Like" + initiates)
# members is now ("Time", "Flies", "Like", "An", "Arrow")
members[0] = "Fruit"
members[2,3] = "A", "Banana"
# members is now ("Fruit", "Flies", "Like", "A", "Banana")

Reversing an Array

reversed = array.rev

array.rev.each(e ->
    # do something with e
    ()
)

Processing Multiple Elements of an Array

a.shift2 = a.shift!, a.shift!
a.pop2 = swap(a.pop!, a.pop!)

friends = "Peter Paul Mary Jim Tim".words
(this, that) = friends.shift2
# this contains Peter, that has Paul, and
# friends has Mary, Jim, and Tim

beverages = "Dew Jolt Cola Sprite Fresca".words
pair = beverages.pop2
# pair[0] contains Sprite, pair[1] has Fresca,
# and beverages has (Dew, Jolt, Cola)

Finding the First List Element That Passes a Test

highest_engineer = employees.find(employee -> employee.category == "engineer")
println("Highest paid engineer is: {highest_engineer.name}")

Finding All Elements in an Array Matching Certain Criteria

bigs = nums.filter(n -> n > 1_000_000)
pigs = users.filter(_, n -> n > 1e7).keys

matching = popen("who").lines.filter(m(, "^gnat "))
engineers = employees.filter(employee -> employee.category == "engineer")

secondary_assistance = applicants.filter(e -> e{Income} >= 26_000 && e{Income} < 30_000)

Sorting an Array Numerically

sorted = sort(non_sorted)               # if non_sorted !> Vector(Int)

# pids is an unsorted array of process IDs
pids.sort.each(println)

println("Select a process ID to kill:")
try
    pid = Sys::stdin.line.chomp.to_int
    pid.kill(TERM)
    sleep(2)
    pid.kill(KILL)
with Failed(To_int) -> die("Exiting ... \n")

descending = non_sorted.sort_by(a,b -> b <=> a)

Sorting a List by Computable Field

ordered = unordered.sort_by(compare)

precomputed = unordered.map(e -> e.compute, e)
ordered_precomputed = precomputed.sort_by(a,b -> a[0] <=> b[0])
ordered = ordered_precomputed.map(a -> a[0])

ordered = unordered.map(e -> e.compute, e)
                   .sort_by(a,b -> a[0] <=> b[0])
                   .map(a -> a[0])

sorted = employees.sort_by(a,b -> a.name <=> b.name || b.age <=> a.age)

# getpwent is an iterator
users = getpwent().to_list
users.sort_by!(a,b -> a{Name} <=> b{Name})
users.each(user -> user{Name}.println)

sorted = names.sort_by(a,b -> a[1] <=> b[1])
sorted = string.sort_by(a,b -> a.size <=> b.size)

sorted_fields = fields.map(e -> e.m("(\d+)"), e)
                      .sort_by(a,b -> a[0] <=> b[0])
                      .map(a -> a[0])

"/etc/passwd".open
    .lmap(e -> e.split(":")[3,2,0], e)
    .sort_by(a,b ->
        a[1] <=> b[1] ||| # gid
        a[2] <=> b[2] ||| # uid
        a[3] <=> b[3]     # login
    )
    .map(a -> a[0])

Implementing a Circular List

circular.unshift!(circular.pop!)        # the last shall be first
circular.push!(circular.shift!)         # and vice versa

l.grab_and_rotate =
    e = l.shift!
    l.push!(e)
    e

processes = (1, 2, 3, 4, 5)
loop
    process = grab_and_rotate(processes)
    println("Handling process {process}")
    sleep(1)

Randomizing an Array

l.randomize!

l.fisher_yates_shuffle =
    (l.size - 1 .. 0).each(i ->
        j = random(i+1)
        l[i,j] = l[j,i] if i != j
    )

l.naive_shuffle =
    l.each_with_index(_, i ->
        j = random(l.size)
        l[i,j] = l[j,i] if i != j
    )

Program: words

Program: permute