Array Utilities
Description
Section titled “Description”This example demonstrates the array utility functions for comparing and concatenating byte arrays:
- arrayEqual() for comparing two arrays element-by-element
- concatArrays() for joining multiple Uint8Arrays into a new array
Prerequisites
Section titled “Prerequisites”- No LocalNet required
Run This Example
Section titled “Run This Example”From the repository root:
cd examplesnpm run example common/03-array-utilities.ts/** * Example: Array Utilities * * This example demonstrates the array utility functions for comparing and * concatenating byte arrays: * - arrayEqual() for comparing two arrays element-by-element * - concatArrays() for joining multiple Uint8Arrays into a new array * * Prerequisites: * - No LocalNet required */
import { arrayEqual, concatArrays } from '@algorandfoundation/algokit-utils/common';import { formatBytes, printHeader, printInfo, printStep, printSuccess } from '../shared/utils.js';
function main() { printHeader('Array Utilities Example');
// Step 1: arrayEqual() - Comparing Equal Arrays printStep(1, 'arrayEqual() - Comparing Equal Arrays');
const arr1 = new Uint8Array([1, 2, 3, 4, 5]); const arr2 = new Uint8Array([1, 2, 3, 4, 5]);
printInfo(`Array 1: ${formatBytes(arr1)}`); printInfo(`Array 2: ${formatBytes(arr2)}`); printInfo(`arrayEqual(arr1, arr2): ${arrayEqual(arr1, arr2)}`); printInfo(`Arrays with identical content return true`);
// Step 2: arrayEqual() - Different Length Arrays printStep(2, 'arrayEqual() - Different Length Arrays');
const shortArr = new Uint8Array([1, 2, 3]); const longArr = new Uint8Array([1, 2, 3, 4, 5]);
printInfo(`Short array (length ${shortArr.length}): ${formatBytes(shortArr)}`); printInfo(`Long array (length ${longArr.length}): ${formatBytes(longArr)}`); printInfo(`arrayEqual(shortArr, longArr): ${arrayEqual(shortArr, longArr)}`); printInfo(`Different lengths return false (fast check before element comparison)`);
// Step 3: arrayEqual() - Same Length, Different Content printStep(3, 'arrayEqual() - Same Length, Different Content');
const arrA = new Uint8Array([1, 2, 3, 4, 5]); const arrB = new Uint8Array([1, 2, 99, 4, 5]); // Different value at index 2
printInfo(`Array A: ${formatBytes(arrA)}`); printInfo(`Array B: ${formatBytes(arrB)}`); printInfo(`arrayEqual(arrA, arrB): ${arrayEqual(arrA, arrB)}`); printInfo(`Same length but different content at index 2 returns false`);
// Step 4: arrayEqual() - Edge Cases printStep(4, 'arrayEqual() - Edge Cases');
// Empty arrays const empty1 = new Uint8Array([]); const empty2 = new Uint8Array([]); printInfo(`Empty arrays: arrayEqual([], []): ${arrayEqual(empty1, empty2)}`);
// Single element const single1 = new Uint8Array([42]); const single2 = new Uint8Array([42]); printInfo(`Single element: arrayEqual([42], [42]): ${arrayEqual(single1, single2)}`);
// Same reference const sameRef = new Uint8Array([1, 2, 3]); printInfo(`Same reference: arrayEqual(arr, arr): ${arrayEqual(sameRef, sameRef)}`);
// Step 5: concatArrays() - Joining Multiple Arrays printStep(5, 'concatArrays() - Joining Multiple Arrays');
const first = new Uint8Array([1, 2, 3]); const second = new Uint8Array([4, 5, 6]); const third = new Uint8Array([7, 8, 9]);
printInfo(`First array: ${formatBytes(first)}`); printInfo(`Second array: ${formatBytes(second)}`); printInfo(`Third array: ${formatBytes(third)}`);
const concatenated = concatArrays(first, second, third); printInfo(`\nconcatArrays(first, second, third):`); printInfo(`Result: ${formatBytes(concatenated)}`); printInfo(`Result length: ${concatenated.length} bytes`);
// Step 6: concatArrays() - Different Sized Arrays printStep(6, 'concatArrays() - Different Sized Arrays');
const tiny = new Uint8Array([1]); const small = new Uint8Array([2, 3]); const medium = new Uint8Array([4, 5, 6, 7]); const large = new Uint8Array([8, 9, 10, 11, 12, 13, 14, 15]);
printInfo(`Tiny (1 byte): ${formatBytes(tiny)}`); printInfo(`Small (2 bytes): ${formatBytes(small)}`); printInfo(`Medium (4 bytes): ${formatBytes(medium)}`); printInfo(`Large (8 bytes): ${formatBytes(large)}`);
const combined = concatArrays(tiny, small, medium, large); printInfo(`\nconcatArrays(tiny, small, medium, large):`); printInfo(`Result: ${formatBytes(combined)}`); printInfo(`Result length: ${combined.length} bytes (1 + 2 + 4 + 8 = 15)`);
// Step 7: concatArrays() Returns New Array (Doesn't Modify Inputs) printStep(7, 'concatArrays() - Returns New Array (Non-Mutating)');
const original1 = new Uint8Array([10, 20, 30]); const original2 = new Uint8Array([40, 50, 60]);
printInfo(`Before concat:`); printInfo(` original1: ${formatBytes(original1)}`); printInfo(` original2: ${formatBytes(original2)}`);
const result = concatArrays(original1, original2);
printInfo(`\nAfter concat:`); printInfo(` original1: ${formatBytes(original1)} (unchanged)`); printInfo(` original2: ${formatBytes(original2)} (unchanged)`); printInfo(` result: ${formatBytes(result)} (new array)`);
// Prove they are different objects printInfo(`\nVerifying result is a new array:`); printInfo(` result === original1: ${result === original1}`); printInfo(` result === original2: ${result === original2}`);
// Modify result and show originals are unaffected result[0] = 99; printInfo(`\nAfter modifying result[0] = 99:`); printInfo(` result: ${formatBytes(result)}`); printInfo(` original1: ${formatBytes(original1)} (still unchanged)`);
// Step 8: concatArrays() - Edge Cases printStep(8, 'concatArrays() - Edge Cases');
// Single array const singleInput = new Uint8Array([1, 2, 3]); const singleResult = concatArrays(singleInput); printInfo(`Single input: concatArrays([1,2,3]) = ${formatBytes(singleResult)}`); printInfo(` Is new array: ${singleResult !== singleInput}`);
// Empty arrays const emptyResult = concatArrays(new Uint8Array([]), new Uint8Array([1, 2]), new Uint8Array([])); printInfo(`With empty arrays: concatArrays([], [1,2], []) = ${formatBytes(emptyResult)}`);
// No arguments const noArgs = concatArrays(); printInfo(`No arguments: concatArrays() = ${formatBytes(noArgs)} (empty array)`);
// Step 9: Practical Use Cases printStep(9, 'Practical Use Cases');
printInfo('Common scenarios for array utilities:');
printInfo('\n1. Comparing cryptographic hashes:'); const hash1 = new Uint8Array([0xab, 0xcd, 0xef, 0x12]); const hash2 = new Uint8Array([0xab, 0xcd, 0xef, 0x12]); printInfo(` hash1 === hash2 (reference): ${hash1 === hash2}`); printInfo(` arrayEqual(hash1, hash2) (content): ${arrayEqual(hash1, hash2)}`);
printInfo('\n2. Building transaction data:'); const prefix = new Uint8Array([0x54, 0x58]); // "TX" const txData = new Uint8Array([0x01, 0x02, 0x03]); const prefixedTx = concatArrays(prefix, txData); printInfo(` Prefix + TxData: ${formatBytes(prefixedTx)}`);
printInfo('\n3. Concatenating signature components:'); const r = new Uint8Array([0x30, 0x31, 0x32, 0x33]); // r component const s = new Uint8Array([0x40, 0x41, 0x42, 0x43]); // s component const signature = concatArrays(r, s); printInfo(` r + s = ${formatBytes(signature)}`);
// Step 10: Summary printStep(10, 'Summary');
printInfo('Array Comparison:'); printInfo(' - arrayEqual(a, b) - Compare two arrays element-by-element'); printInfo(' - Returns false immediately if lengths differ (efficient)'); printInfo(' - Works with any ArrayLike<T> type');
printInfo('\nArray Concatenation:'); printInfo(' - concatArrays(...arrays) - Join multiple Uint8Arrays'); printInfo(' - Returns a new Uint8Array (non-mutating)'); printInfo(' - Works with any ArrayLike<number> type'); printInfo(' - Handles empty arrays and single inputs gracefully');
printSuccess('Array Utilities example completed successfully!');}
main();