Skip to content

Arrays

Module Arrays

ixfx has a host of functions for working with arrays. See the link above for a complete overview. On this page we’ll give a quick overview of working with arrays in Javascript interleaved with some ixfx functions.

In Javascript, arrays are essentially stacks, with items stored ‘left-to-right’ in the order added. Arrays can hold whatever you want, sometimes we even use arrays to hold other arrays, a way of making a multi-dimensional data structure like a table.

Arrays in Javascript are mutable meaning their contents can change even though the object reference stays the same. In this document, we’ll only use them in an immutable way.

Arrays are simple to create

// Create an empty array
const a1 = [];
// Create with some starting elements
const a2 = ['starting'];
const a3 = ['one', 'two'];
// Create using the contents of other arrays
const a4 = [...a2, ...a3]; // ['starting', 'one', 'two']

Create an array from an iterable or generator

Array.from(iterable);

When working with immutable arrays, we don’t actually add anything to an array, but rather create a new array with previous elements and any new elements.

Use destructuring to add element(s) to an array. Where you put the destructured values will determine their position. Let’s say ‘a’ is the initial array.

const a = ['some','array']
const b = [...a, 'with', 'new']; // ['some','array','with','new']
const c = ['with', 'new', ...a]; // ['with', 'new', 'some', 'array']
const d = ['with', ...a, 'new']; // ['with', 'some', 'array', 'new']

Note in these cases, a never changes.

To filter is to go through every item in an array and see if it matches a condition, called a predicate. If the predicate returns true, the item is returned, forming a new array. The original array is not changed.

const a = [`apple`,`banana`,`carrot`,`bean`];
// Check if item starts with letter b
const withB = a.filter( v => v.startsWith(`b`)); // [`banana`, `bean`]

In the above example we’re using a succint way to express the predicate. But it could be expanded as below, just make sure it returns true or false.

const a = [`apple`,`banana`,`carrot`,`bean`];
// Get items at 50% chance
const r = a.filter( v => {
const r = Math.random();
if (r > 0.5) return false;
return true; // Item will be included
});
// This could be expressed in more compressed form as: a.filter(v => Math.random() > 0.5)

filter will return an empty array if no matching items were found.

When working with immutable arrays, we don’t really remove items, but rather create a new array without certain items. filter comes in handy for this.

For example, we want an array without carrot:

const a = [`apple`,`banana`,`carrot`,`bean`];
const withoutCarrot = a.filter( v => v === `carrot`); // [`apple`,`banana`,`bean`]

If it seems ugly to always create new variables when using immutable arrays, use let rather than const:

let a = [`apple`,`banana`,`carrot`,`bean`];
a = a.filter( v => v === `carrot`); // [`apple`,`banana`,`bean`]

You can ‘loop over’ or ‘enumerate’ the contents of an array.

// for-of
for (const v of myArray) {
// 'v' will be an item from array
}
// forEach
myArray.forEach(v => {
// 'v' will be an item from array
})

Items in arrays have an integer index, which starts at 0. Meaning the first item is at position in 0. Use at to get an item by index. If you use negative numbers it will count from the last element.

const ar = ['a','b','c','d'];
// First
ar.at(0); // 'a'
// Second, etc
ar.at(1); // 'b'
// Last
ar.at(-1); // 'd'

filter can be used to find items that match a predicate and return a new array. However there are times you just want to check if something exists, without getting it back.

some allows you to use a filtering predicate:

const ar = ['apple','banana','carrot'];
if (ar.some( v => v.startsWith(`b`))) {
// do something if we have an item that starts with 'b'...
}

find allows you to use a filtering predicate, returning the first item that matches.

const ar = ['apple','banana','carrot','bean'];
const anythingB = ar.find( v => v.startsWith(`b`)); // `banana`
if (anythingB) {
// Do something if we find any item starting with 'b'...
}

find will return undefined if no matching item was found.

ixfx has functions for getting a random element or index:

import { randomElement, randomIndex, shuffle } from 'https://unpkg.com/@ixfx/arrays/bundle';
const v = [`blue`, `red`, `orange`, `pink`, `purple`];
randomElement(v);
randomIndex(v);
// Randomise order
const shuffled = shuffle(v);

weightedSource can be used for skewing the distributing of random elements, eg. to favour picking elements at the end of the array over elements at the beginning.

import { weightedSource } from 'https://unpkg.com/@ixfx/modulation/bundle';
import { randomElement } from 'https://unpkg.com/@ixfx/arrays/bundle';
const v = [`blue`, `red`, `orange`, `pink`, `purple`];
// Favour items in the middle
randomElement(v, weightedSource(`bell`));

Remove a random element from an array with randomPluck . It doesn’t modify the array, but returns the randomly selected item and a new array without it.

import {randomPluck} from 'https://unpkg.com/@ixfx/random/bundle';
const r = randomPluck([`apples`, `oranges`, `pears`]);
r.value; // A random value
r.remainder; // Remaining values

Or you can use the mutate option to modify the source:

import {randomPluck} from 'https://unpkg.com/@ixfx/random/bundle';
let source = [`apples`, `oranges`, `pears`];
const r = randomPluck(source, { mutate: true }); // Some random value

ixfx has sorting functions for common needs: sortByProperty , sortByNumericProperty

import { sortByProperty, sortByNumericProperty } from 'https://unpkg.com/@ixfx/arrays/bundle';
const v = [
{ colour:`blue`, size: 10 },
{ colour:`red`, size: 5 },
{ colour:`orange`, size: 7 },
{ colour:`pink`, size: 1 }
];
// Sort objects by their 'colour' property
const byColour = sortByProperty(v, `colour`);
// Sort objects by their 'size' property
const bySize = sortByNumericProperty(v, `size`);

groupBy allows you to group an array by some generated key.

import { groupBy } from "https://unpkg.com/@ixfx/arrays/bundle"
const data = [
{ age: 39, city: `London` },
{ age: 14, city: `Copenhagen` },
{ age: 23, city: `Stockholm` },
{ age: 56, city: `London` }
];
const map = groupBy(data, item => item.city); // Get back a Map
console.log(map);

This will yield the Map:

{
London: [
{ age: 39, city: `London` },
{ age: 56, city: `London` }
],
Stockhom: [
{ age: 23, city: `Stockholm` }
],
Copenhagen: [
{ age: 14, city: `Copenhagen` }
]
}
// Whole module
import * as Arrays from "@ixfx/arrays"
// Single function
import { shuffle } from "@ixfx/arrays"
// One of several modules
import { Arrays, Modulation, Flow, Data } from "@ixfx"
// And within your HTML's <HEAD> </HEAD> block:
<script type="importmap">{ "imports": { "@ixfx":"/ixfx/index.js", "@ixfx/": "/ixfx/" } }</script>