Lists in Bitbybit
View Full Source & Details on GitHub
bitbybit.lists reads, builds and reshapes lists. A list is a plain JavaScript array, so it can hold anything: numbers, texts, points, shapes, or other lists, as in [1, 2, 3], ["apple", "banana"] or [[0,0,0], [1,1,1]].
Two rules first
- Positions count from 0: index 0 is the first item.
clonekeeps your input as it was. Most functions take acloneoption, on by default, that deep-copies the list (withstructuredClone) before working on it. Switched off, the functions that add, remove, reverse, shuffle or sort change the list you pass in, which is faster on large data. Data with circular references cannot be copied, and cloning it throws.removeAllItemshas no such option: it always empties the list it is given.
Building lists
createEmptyListgives[].repeatgives a list that holds the same itemtimestimes.repeatInPatternrepeats a list of items over and over until the result islengthLimitlong, so[1, 2, 3]to length 7 gives[1, 2, 3, 1, 2, 3, 1].concatenatejoins several lists end to end.
Reading items
getItemreads the item at an index; an index outside the list throws.getFirstItemandgetLastItemread the ends and throw on an empty list.getSubListcuts out the items fromindexStartup to, but not including,indexEnd.getNthItemkeeps everynthitem: an item is kept when its index plusoffsetdivides evenly bynth.getByPatternkeeps the items where a repeating true/false pattern says true.randomGetThresholdkeeps each item with probabilitythreshold, so the result differs on every call.includestells whether an item is in the list andfindIndexgives its first index, or -1. Both compare by identity: an object is found only if the very same object is in the list.
Here getNthItem keeps every second of two hundred spiral points, and a smooth curve passes through the points kept:
- Rete
- Blockly
- TypeScript
Script Source (rete)
{
"id": "rete-v2-json",
"nodes": {
"spiral": {
"id": "spiral",
"name": "bitbybit.point.spiral",
"customName": "spiral",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"phi": 0.9,
"numberPoints": 200,
"widening": 3,
"radius": 6,
"factor": 1
},
"inputs": {},
"position": [
40,
40
]
},
"kept": {
"id": "kept",
"name": "bitbybit.lists.getNthItem",
"customName": "get nth item",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"nth": 2,
"offset": 0,
"clone": true
},
"inputs": {
"list": {
"connections": [
{
"node": "spiral",
"output": "result",
"data": {}
}
]
}
},
"position": [
460,
40
]
},
"curve": {
"id": "curve",
"name": "bitbybit.occt.shapes.wire.interpolatePoints",
"customName": "interpolate points",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"periodic": false,
"tolerance": 1e-7,
"parametrization": "chordLength"
},
"inputs": {
"points": {
"connections": [
{
"node": "kept",
"output": "result",
"data": {}
}
]
}
},
"position": [
880,
40
]
}
},
"modules": {}
}
Script Source (blockly)
<xml xmlns="https://developers.google.com/blockly/xml"><variables><variable id="points">points</variable></variables><block type="variables_set" x="40" y="40"><field name="VAR" id="points">points</field><value name="VALUE"><block type="bitbybit.point.spiral"><value name="Phi"><block type="math_number"><field name="NUM">0.9</field></block></value><value name="NumberPoints"><block type="math_number"><field name="NUM">200</field></block></value><value name="Widening"><block type="math_number"><field name="NUM">3</field></block></value><value name="Radius"><block type="math_number"><field name="NUM">6</field></block></value><value name="Factor"><block type="math_number"><field name="NUM">1</field></block></value></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn"><value name="Entity"><block type="variables_get"><field name="VAR" id="points">points</field></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn"><value name="Entity"><block type="bitbybit.occt.shapes.wire.interpolatePoints"><value name="Points"><block type="bitbybit.lists.getNthItem"><value name="List"><block type="variables_get"><field name="VAR" id="points">points</field></block></value><value name="Nth"><block type="math_number"><field name="NUM">2</field></block></value><value name="Offset"><block type="math_number"><field name="NUM">0</field></block></value><value name="Clone"><block type="logic_boolean"><field name="BOOL">TRUE</field></block></value></block></value><value name="Periodic"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="Tolerance"><block type="math_number"><field name="NUM">1e-7</field></block></value><value name="Parametrization"><block type="bitbybit.occt.enums.bSplineParametrizationEnum"><field name="bitbybit.occt.enums.bSplineParametrizationEnum">'chordLength'</field></block></value></block></value></block></next></block></next></block></xml>
Script Source (typescript)
const points = bitbybit.point.spiral({ numberPoints: 200, radius: 6, phi: 0.9, widening: 3, factor: 1 });
const kept = bitbybit.lists.getNthItem({ list: points, nth: 2, offset: 0, clone: true });
const curve = await bitbybit.occt.shapes.wire.interpolatePoints({ points: kept });
await bitbybit.draw.drawAnyAsync({ entity: points });
await bitbybit.draw.drawAnyAsync({ entity: curve });
Measuring
listLengthcounts the items.getListDepthgives how deeply lists are nested:[1, 2]is 1,[[1, 2], [3]]is 2.getLongestListLengthgives the length of the longest of several lists.
Adding and removing items
addItemadds an item at the end,prependItemat the start, andaddItemFirstLastat whichever endpositionnames.addItemAtIndexinserts an item at an index.addItemAtIndexesinserts the same item at several indexes, andaddItemsAtIndexesinserts one item per index; both count the indexes on the list as it was before any insertion.addItemsAtIndexesthrows unless there is one index per item, in ascending order.removeItemAtIndexremoves the item at an index, andremoveItemAtIndexFromEndcounts from the end, where 0 is the last item.removeItemsAtIndexesremoves several, all counted on the original list.removeFirstItemandremoveLastItemremove the ends. Indexes outside the list are ignored.removeNthItemremoves the itemsgetNthItemwould keep, andrandomRemoveThresholddrops each item with probabilitythreshold.removeAllItemsempties the list in place.
Removing duplicates
removeDuplicateskeeps the first occurrence of each item, comparing by identity, so two equal-looking objects both stay.removeDuplicateNumbersdoes the same for numbers, andremoveDuplicateNumbersTolerancealso counts numbers closer thantolerance(default1e-7) as the same, so floating-point noise does not leave near copies.
Reshaping
reversereverses the order;shuffleputs the items in a random order.groupNthsplits the list into groups ofnrElements. Items left over at the end are dropped unlesskeepRemainderis on.flipListsturns a list of lists on its side, so rows become columns:[[0, 1, 2], [3, 4, 5]]gives[[0, 3], [1, 4], [2, 5]]. The inner lists must all have the same length, or it throws.mergeElementsOfListsregroups lists by position, the first items together, then the second, and so on. UnlikeflipListsit accepts lists of different lengths.levelsays how deep inside each list to regroup, and the result keeps that much nesting around the groups.interleaveweaves lists into one, taking the first item of each, then the second of each:[[0, 1, 2], [3, 4, 5]]gives[0, 3, 1, 4, 2, 5]. A shorter list drops out once it runs dry.
Sorting
sortNumbersorts numbers, lowest first whenorderAscis on (the default) or highest first.sortTextssorts texts by character code, so capitals come before lower case:["b", "a", "C"]gives["C", "a", "b"].sortByPropValuesorts objects by the number held in theirproperty.
Every function
| Function | What it does |
|---|---|
addItem | Adds an item at the end of the list. |
addItemAtIndex | Inserts an item at a position; the items from that position on shift up by one. |
addItemAtIndexes | Inserts the same item at several positions of the original list. |
addItemFirstLast | Adds an item at the start or at the end of the list, as chosen. |
addItemsAtIndexes | Inserts several items, the first at the first index, the second at the second, and so on, all counted on the original list. |
concatenate | Joins several lists into one, end to end. |
createEmptyList | Makes a new list with nothing in it. |
findIndex | Finds the position of the first occurrence of an item, or -1 when it is not in the list. |
flipLists | Turns a list of lists on its side: rows become columns and columns become rows. |
getByPattern | Keeps the items where a repeating true/false pattern says true and drops the others. |
getFirstItem | Reads the first item of the list. |
getItem | Reads the item at a position in the list, counting from 0. |
getLastItem | Reads the last item of the list. |
getListDepth | Measures how deeply lists are nested inside the list. |
getLongestListLength | Measures the longest list among several. |
getNthItem | Keeps every nth item, starting from an offset. |
getSubList | Cuts out the items from a start index up to, but not including, an end index. |
groupNth | Splits the list into groups of n items. |
includes | Tells whether an item is in the list. |
interleave | Weaves several lists into one by taking the first item of each in turn, then the second of each, and so on. |
listLength | Counts the items in the list. |
mergeElementsOfLists | Regroups nested lists by position: the first items of every list go together, then the second items, and so on. |
prependItem | Adds an item at the start of the list. |
randomGetThreshold | Keeps each item of the list with a given probability and drops the rest, so the result differs on every call. |
randomRemoveThreshold | Drops each item of the list with a given probability and keeps the rest, so the result differs on every call. |
removeAllItems | Empties the list it is given, in place: the same array comes back with no items in it. |
removeDuplicateNumbers | Removes repeated numbers, keeping the first occurrence of each. |
removeDuplicateNumbersTolerance | Removes numbers that are within a tolerance of one already kept, so values that differ only by floating-point noise count as the same. |
removeDuplicates | Removes repeated items of any kind, keeping the first occurrence of each. |
removeFirstItem | Removes the first item. |
removeItemAtIndex | Removes the item at a position. |
removeItemAtIndexFromEnd | Removes an item counted from the end: index 0 is the last item, 1 the one before it. |
removeItemsAtIndexes | Removes the items at several positions, all counted on the original list. |
removeLastItem | Removes the last item. |
removeNthItem | Removes every nth item, starting from an offset. |
repeat | Makes a list that holds the same item a number of times. |
repeatInPattern | Repeats a pattern of items over and over until the list reaches a given length. |
reverse | Reverses the order of the items. |
shuffle | Puts the items in a random order, different on every call. |
sortByPropValue | Sorts objects by the number held in one of their properties. |
sortNumber | Sorts numbers from lowest to highest, or from highest to lowest. |
sortTexts | Sorts texts alphabetically, from A to Z or from Z to A. |



