Arrays
Utah provides powerful built-in functions for working with arrays, making data manipulation intuitive and type-safe.
Arrays
Declaration and Initialization
// Empty array
let users: string[] = [];
// Array with initial values
let numbers: number[] = [1, 2, 3, 4, 5];
// Mixed types (object array)
let items: object[] = [];
Array Methods
Utah supports array functions using namespace syntax:
Syntax: array.function(arrayVariable, ...args)
- Clear and consistent with other built-in functions
array.length()
Get the number of elements in an array:
let fruits: string[] = ["apple", "banana", "orange"];
let count: number = array.length(fruits); // Namespace syntax
console.log("We have ${count} fruits");
array.contains()
Check if an array contains a specific value:
let languages: string[] = ["javascript", "python", "go"];
if (array.contains(languages, "python")) {
console.log("Python is supported");
}
array.isEmpty()
Check if an array is empty:
let tasks: string[] = [];
// Check if array is empty:
if (array.isEmpty(tasks)) { // Namespace syntax
console.log("No tasks pending");
}
array.reverse()
Reverse the order of elements:
let numbers: number[] = [1, 2, 3, 4, 5];
let reversed: number[] = array.reverse(numbers);
// reversed is [5, 4, 3, 2, 1]
array.join()
Join array elements into a string with a separator:
let fruits: string[] = ["apple", "banana", "cherry"];
// Join with default separator (comma)
let defaultJoin: string = array.join(fruits); // "apple,banana,cherry"
// Join with custom separators
let pipeJoin: string = array.join(fruits, " | "); // "apple | banana | cherry"
let dashJoin: string = array.join(fruits, "-"); // "apple-banana-cherry"
let spaceJoin: string = array.join(fruits, " "); // "apple banana cherry"
// Join different array types
let numbers: number[] = [1, 2, 3, 4, 5];
let numberString: string = array.join(numbers, "-"); // "1-2-3-4-5"
// Use in string interpolation
console.log("Fruits: ${array.join(fruits, ", ")}"); // "Fruits: apple, banana, cherry"
array.sort()
Sort array elements in ascending or descending order:
let numbers: number[] = [3, 1, 4, 1, 5, 9, 2, 6];
let fruits: string[] = ["banana", "apple", "cherry", "date"];
let flags: boolean[] = [true, false, true, false];
// Sort with default order (ascending)
let numbersAsc: number[] = array.sort(numbers); // [1, 1, 2, 3, 4, 5, 6, 9]
let fruitsAsc: string[] = array.sort(fruits); // ["apple", "banana", "cherry", "date"]
let flagsAsc: boolean[] = array.sort(flags); // [false, false, true, true]
// Sort with explicit ascending order
let numbersAscExplicit: number[] = array.sort(numbers, "asc");
// Sort with descending order
let numbersDesc: number[] = array.sort(numbers, "desc"); // [9, 6, 5, 4, 3, 2, 1, 1]
let fruitsDesc: string[] = array.sort(fruits, "desc"); // ["date", "cherry", "banana", "apple"]
// Original arrays remain unchanged - sort() returns a new array
console.log("Original: ${array.join(numbers, ", ")}"); // Still [3, 1, 4, 1, 5, 9, 2, 6]
console.log("Sorted: ${array.join(numbersAsc, ", ")}"); // [1, 1, 2, 3, 4, 5, 6, 9]
// Use with different data types
// - string[]: Lexicographic (alphabetical) sorting
// - number[]: Numeric sorting
// - boolean[]: false before true (false = 0, true = 1)
// Edge cases
let empty: string[] = [];
let emptySorted: string[] = array.sort(empty); // []
let single: number[] = [42];
let singleSorted: number[] = array.sort(single); // [42]
// Chain with other array methods
let topThreeNumbers: string = array.join(array.sort(numbers, "desc"), ", ");
Array Merging
Basic Merging
Combine two arrays of the same type:
// String array merging
let names: string[] = ["alice", "bob"];
let moreNames: string[] = ["charlie", "diana"];
let allNames: string[] = array.merge(names, moreNames); // ["alice", "bob", "charlie", "diana"]
// Number array merging
let numbers1: number[] = [1, 2, 3];
let numbers2: number[] = [4, 5, 6];
let allNumbers: number[] = array.merge(numbers1, numbers2); // [1, 2, 3, 4, 5, 6]
// Boolean array merging
let flags1: boolean[] = [true, false];
let flags2: boolean[] = [false, true];
let allFlags: boolean[] = array.merge(flags1, flags2); // [true, false, false, true]
Edge Cases
// Merging with empty arrays
let letters: string[] = ["a", "b"];
let empty: string[] = [];
let result1: string[] = array.merge(letters, empty); // ["a", "b"]
let result2: string[] = array.merge(empty, letters); // ["a", "b"]
let result3: string[] = array.merge(empty, empty); // []
// Single element arrays
let single1: number[] = [100];
let single2: number[] = [200];
let merged: number[] = array.merge(single1, single2); // [100, 200]
Chaining with Other Array Methods
// Merge then sort
let list1: string[] = ["zebra", "apple"];
let list2: string[] = ["banana", "cherry"];
let sortedMerged: string[] = array.sort(array.merge(list1, list2)); // ["apple", "banana", "cherry", "zebra"]
// Sort then merge (preserves sort order)
let sorted1: number[] = array.sort([3, 1, 4]); // [1, 3, 4]
let sorted2: number[] = array.sort([2, 6, 5]); // [2, 5, 6]
let finalMerged: number[] = array.merge(sorted1, sorted2); // [1, 3, 4, 2, 5, 6]
// Complex chaining
let words1: string[] = ["hello", "world"];
let words2: string[] = ["utah", "lang"];
let sentence: string = array.join(array.merge(words1, words2), " "); // "hello world utah lang"
Array Shuffling
Basic Shuffling
Randomly shuffle array elements using the array.shuffle()
function:
// String array shuffling
let names: string[] = ["alice", "bob", "charlie", "diana"];
let shuffledNames: string[] = array.shuffle(names); // Random order like ["charlie", "alice", "diana", "bob"]
// Number array shuffling
let numbers: number[] = [1, 2, 3, 4, 5];
let shuffledNumbers: number[] = array.shuffle(numbers); // Random order like [3, 1, 5, 2, 4]
// Boolean array shuffling
let flags: boolean[] = [true, false, true, false];
let shuffledFlags: boolean[] = array.shuffle(flags); // Random order like [false, true, false, true]
Shuffle Edge Cases
// Shuffling empty arrays
let empty: string[] = [];
let shuffledEmpty: string[] = array.shuffle(empty); // []
// Single element arrays
let single: number[] = [42];
let shuffledSingle: number[] = array.shuffle(single); // [42]
// Two element arrays
let pair: string[] = ["first", "second"];
let shuffledPair: string[] = array.shuffle(pair); // Either ["first", "second"] or ["second", "first"]
Practical Use Cases
// Card shuffling for games
let deck: string[] = ["A♠", "K♠", "Q♠", "J♠", "10♠", "9♠", "8♠", "7♠"];
let shuffledDeck: string[] = array.shuffle(deck);
console.log("Shuffled deck: " + array.join(shuffledDeck, ", "));
// Random question order for quizzes
let questions: string[] = ["What is 2+2?", "What is the capital of France?", "Who wrote Romeo and Juliet?"];
let randomizedQuestions: string[] = array.shuffle(questions);
// Random player order for games
let players: string[] = ["Alice", "Bob", "Charlie", "Diana"];
let gameOrder: string[] = array.shuffle(players);
console.log("Player order: " + array.join(gameOrder, " -> "));
// Random selection from pool
let colors: string[] = ["red", "blue", "green", "yellow", "purple"];
let shuffledColors: string[] = array.shuffle(colors);
let randomColor: string = shuffledColors[0]; // First element of shuffled array
console.log("Random color selected: " + randomColor);
Shuffle Chaining with Other Array Methods
// Shuffle then take first N elements
let items: string[] = ["item1", "item2", "item3", "item4", "item5"];
let shuffledItems: string[] = array.shuffle(items);
let randomThree: string = array.join([shuffledItems[0], shuffledItems[1], shuffledItems[2]], ", ");
// Sort then shuffle (useful for testing)
let sorted: number[] = array.sort([5, 1, 3, 2, 4]); // [1, 2, 3, 4, 5]
let shuffledSorted: number[] = array.shuffle(sorted); // Random order of sorted elements
// Multiple shuffles produce different results
let originalDeck: string[] = ["A", "K", "Q", "J"];
let shuffle1: string[] = array.shuffle(originalDeck);
let shuffle2: string[] = array.shuffle(originalDeck);
// shuffle1 and shuffle2 will likely have different orders
// Use in conditionals
if (!array.isEmpty(array.shuffle(numbers))) {
console.log("Shuffled array contains elements");
}
Array Deduplication
Basic Unique Operations
Remove duplicate elements from arrays using the array.unique()
function:
// String array deduplication
let names: string[] = ["alice", "bob", "alice", "charlie", "bob"];
let uniqueNames: string[] = array.unique(names); // ["alice", "bob", "charlie"]
// Number array deduplication
let numbers: number[] = [1, 2, 2, 3, 1, 4, 3, 5];
let uniqueNumbers: number[] = array.unique(numbers); // [1, 2, 3, 4, 5]
// Boolean array deduplication
let flags: boolean[] = [true, false, true, false, true];
let uniqueFlags: boolean[] = array.unique(flags); // [true, false]
Order Preservation
The array.unique()
function preserves the order of first occurrence:
// First occurrence order is maintained
let items: string[] = ["c", "a", "b", "a", "c", "d", "b"];
let uniqueItems: string[] = array.unique(items); // ["c", "a", "b", "d"]
// Even with numbers, first occurrence is preserved
let data: number[] = [5, 2, 8, 2, 1, 5, 3];
let uniqueData: number[] = array.unique(data); // [5, 2, 8, 1, 3]
Unique Edge Cases
// Empty arrays
let empty: string[] = [];
let uniqueEmpty: string[] = array.unique(empty); // []
// Single element arrays
let single: number[] = [42];
let uniqueSingle: number[] = array.unique(single); // [42]
// No duplicates
let noDuplicates: string[] = ["a", "b", "c"];
let stillUnique: string[] = array.unique(noDuplicates); // ["a", "b", "c"]
// All duplicates
let allSame: number[] = [7, 7, 7, 7];
let onlyOne: number[] = array.unique(allSame); // [7]
Deduplication Use Cases
// Remove duplicates from user input
let userTags: string[] = ["javascript", "typescript", "javascript", "react", "typescript"];
let cleanTags: string[] = array.unique(userTags);
console.log("Clean tags: " + array.join(cleanTags, ", "));
// Deduplicate merged data
let list1: string[] = ["apple", "banana"];
let list2: string[] = ["banana", "cherry", "apple"];
let combined: string[] = array.merge(list1, list2); // ["apple", "banana", "banana", "cherry", "apple"]
let uniqueCombined: string[] = array.unique(combined); // ["apple", "banana", "cherry"]
// Data cleaning pipeline
let rawData: number[] = [10, 20, 10, 30, 20, 40];
let cleanData: number[] = array.unique(rawData);
console.log("Removed " + (array.length(rawData) - array.length(cleanData)) + " duplicates");
// Configuration options deduplication
let defaultSettings: string[] = ["debug", "verbose"];
let userSettings: string[] = ["verbose", "production", "debug"];
let allSettings: string[] = array.unique(array.merge(defaultSettings, userSettings));
console.log("Final settings: " + array.join(allSettings, ", "));
Unique Chaining with Other Array Methods
// Unique then sort
let unsorted: number[] = [5, 2, 8, 2, 1, 5, 3];
let sortedUnique: number[] = array.sort(array.unique(unsorted)); // [1, 2, 3, 5, 8]
// Sort then unique (same result for this case)
let uniqueSorted: number[] = array.unique(array.sort(unsorted)); // [1, 2, 3, 5, 8]
// Complex chaining
let words1: string[] = ["hello", "world", "hello"];
let words2: string[] = ["world", "utah", "hello"];
let processedWords: string[] = array.sort(array.unique(array.merge(words1, words2)));
console.log("Final words: " + array.join(processedWords, ", ")); // "hello, utah, world"
// Use in data analysis
let responses: string[] = ["yes", "no", "yes", "maybe", "no", "yes"];
let uniqueResponses: string[] = array.unique(responses);
console.log("Response types: " + array.length(uniqueResponses)); // 3
// Filter duplicates before processing
let ids: number[] = [1, 2, 3, 2, 4, 1, 5];
let uniqueIds: number[] = array.unique(ids);
for (let id: number in uniqueIds) {
console.log("Processing ID: " + id);
}
Array Iteration
For-In Loops
Iterate over array elements:
let servers: string[] = ["web1", "web2", "db1"];
for (let server: string in servers) {
console.log("Checking server: ${server}");
}
Traditional For Loops
Use index-based iteration:
let files: string[] = ["file1.txt", "file2.txt", "file3.txt"];
for (let i: number = 0; i < array.length(files); i++) {
console.log("Processing file ${i + 1}: ${files[i]}");
}
forEach Function
Iterate over arrays with advanced control using the array.forEach()
function:
// Basic forEach with single parameter
let fruits: string[] = ["apple", "banana", "cherry"];
array.forEach(fruits, (fruit) => {
console.log("Processing: ${fruit}");
});
// forEach with index parameter
let servers: string[] = ["web1", "web2", "web3"];
array.forEach(servers, (server, index) => {
console.log("Server ${index}: ${server}");
});
// Multi-line callback for complex operations
let users: string[] = ["alice", "bob", "charlie"];
array.forEach(users, (user) => {
console.log("Processing user: ${user}");
let upperUser: string = string.toUpperCase(user);
console.log("Uppercase: ${upperUser}");
// Use any Utah language features within forEach
if (string.contains(user, "a")) {
console.log("User ${user} contains 'a'");
}
});
// forEach with complex array expressions
array.forEach(string.split("red,green,blue", ","), (color, idx) => {
console.log("Color ${idx}: ${color}");
});
// Data processing with forEach
let logFiles: string[] = ["app.log", "error.log", "access.log"];
array.forEach(logFiles, (logFile) => {
if (fs.exists(logFile)) {
console.log("Processing log file: ${logFile}");
// Process the file content here
} else {
console.log("Log file not found: ${logFile}");
}
});
// Combine forEach with other array functions
let numbers: number[] = [5, 2, 8, 1, 9];
let sortedNumbers: number[] = array.sort(numbers);
array.forEach(sortedNumbers, (value, position) => {
console.log("Position ${position}: ${value}");
});
When to Use Each Iteration Method
- For-in loops: Simple iteration when you only need the element value
- Traditional for loops: When you need precise index control or complex loop logic
- forEach function: When you need both element and index, or when performing complex operations on each element
Common Array Patterns
Processing File Lists
let files: string[] = ["config.json", "data.csv", "script.sh"];
for (let file: string in files) {
if (string.endsWith(file, ".json")) {
console.log("Processing JSON file: ${file}");
}
else if (string.endsWith(file, ".csv")) {
console.log("Processing CSV file: ${file}");
}
else {
console.log("Skipping unknown file type: ${file}");
}
}
Building Command Arguments
let baseCommand: string = "docker run";
let options: string[] = ["-d", "--name myapp", "-p 8080:80"];
let image: string = "nginx:latest";
let command: string = baseCommand;
for (let option: string in options) {
command = "${command} ${option}";
}
command = "${command} ${image}";
console.log("Running: ${command}");
Path Manipulation
let basePath: string = "/var/www";
let projects: string[] = ["project1", "project2", "project3"];
for (let project: string in projects) {
let fullPath: string = "${basePath}/${project}";
if (fs.exists(fullPath)) {
console.log("Found project: ${fullPath}");
}
}
Data Validation
let emails: string[] = ["user@example.com", "invalid-email", "admin@site.org"];
for (let email: string in emails) {
if (string.contains(email, "@") && string.contains(email, ".")) {
console.log("Valid email: ${email}");
}
else {
console.log("Invalid email: ${email}");
}
}
Array Type Safety
Arrays in Utah are strongly typed:
// Type-safe array operations
let numbers: number[] = [1, 2, 3];
let strings: string[] = ["a", "b", "c"];
// This would cause a compile error:
// numbers[0] = "invalid"; // Error: Cannot assign string to number
Array Performance Tips
- Pre-allocate arrays when possible to avoid frequent resizing
- Use appropriate methods for your use case (contains vs iteration)
- Cache array lengths in loops to avoid repeated calculations
- Use array.join() instead of repeated string concatenation
Array Error Handling
Always validate inputs when working with arrays:
function processArray(items: string[]): void {
if (array.isEmpty(items)) {
console.log("Warning: Empty array provided");
return;
}
for (let item: string in items) {
if (string.length(item) == 0) {
console.log("Warning: Empty string found, skipping");
continue;
}
// Process item
console.log("Processing: ${item}");
}
}
Arrays provide the foundation for data collection and manipulation in Utah, offering type-safe operations with familiar syntax and powerful built-in functions.