SkillAgentSearch skills...

Lo.zig

A Lodash-style Zig library

Install / Use

/learn @OrlovEvgeny/Lo.zig
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

CI Release Zig

lo.zig is a Lodash-style Zig library

<p align="center"> <img src="assets/logo.png" alt="lo.zig" width="900"/> </p>

Generic utility library for Zig

Zero hidden allocations: functions that need memory take an Allocator. Iterator-first: most transformations return lazy iterators.

Installation

Add lo.zig as a dependency in your build.zig.zon:

zig fetch --save git+https://github.com/OrlovEvgeny/lo.zig

Then in your build.zig:

const lo_dep = b.dependency("lo", .{
    .target = target,
    .optimize = optimize,
});
exe.root_module.addImport("lo", lo_dep.module("lo"));

Quick Start

const lo = @import("lo");

const total = lo.sum(i32, &.{ 1, 2, 3, 4 }); // 10
const head  = lo.first(i32, &.{ 10, 20, 30 }); // 10
const safe  = lo.unwrapOr(i32, null, 42); // 42

Function Index

  • Slice Helpers - first, last, nth, firstOr, lastOr, nthOr, initial, tail, drop, dropRight, dropWhile, dropWhileAlloc, dropRightWhile, take, takeRight, takeWhile, takeWhileAlloc, takeRightWhile, sample, samples
  • Transform - map, mapAlloc, mapIndex, filter, filterAlloc, reject, rejectAlloc, compact, compactAlloc, flatten, flattenAlloc, flattenDeep, flatMap, flatMapAlloc, without, forEach, forEachIndex, compactMap, filterMapIter
  • Aggregate - reduce, reduceRight, sum, sumBy, product, productBy, mean, meanBy, min, max, minBy, maxBy, minMax, minMaxBy, count, countBy, countValues, mode, median, variance, stddev, sampleVariance, sampleStddev, percentile
  • Sort & Order - sortBy, sortByAlloc, sortByField, sortByFieldAlloc, toSortedAlloc, isSorted, equal, reverse, shuffle
  • Set Operations - uniq, uniqBy, intersect, union_, difference, symmetricDifference, findDuplicates, findUniques, elementsMatch, differenceWith, intersectWith, unionWith
  • Partition & Group - partition, groupBy, chunk, window, scan, scanAlloc
  • Combine - concat, splice, interleave, fill, fillRange, repeat, repeatBy, times, timesAlloc
  • Search - find, findIndex, findLast, findLastIndex, indexOf, lastIndexOf, contains, containsBy, every, some, none, minIndex, maxIndex, binarySearch, lowerBound, upperBound, sortedIndex, sortedLastIndex
  • Map Helpers - keys, keysAlloc, values, valuesAlloc, entries, entriesAlloc, fromEntries, mapKeys, mapValues, filterMap, filterKeys, filterValues, pickKeys, omitKeys, invert, merge, assign, mapEntries, mapToSlice, valueOr, hasKey, mapCount, keyBy, associate
  • String Helpers - words, wordsAlloc, camelCase, pascalCase, snakeCase, kebabCase, capitalize, lowerFirst, toLower, toUpper, trim, trimStart, trimEnd, startsWith, endsWith, includes, substr, ellipsis, strRepeat, padLeft, padRight, runeLength, randomString, split, splitAlloc, join, replace, replaceAll, chunkString
  • Math - sum, mean, median, variance, stddev, sampleVariance, sampleStddev, percentile, lerp, remap, clamp, inRange, cumSum, cumProd, rangeAlloc, rangeWithStepAlloc
  • Tuple Helpers - zip, zipAlloc, zipWith, unzip, enumerate
  • Type Helpers - isNull, isNotNull, unwrapOr, coalesce, empty, isEmpty, isNotEmpty, ternary, toConst
  • Types - Entry, Pair, MinMax, RangeError, PartitionResult, UnzipResult, AssocEntry, and iterator types

Slice Helpers

first

Returns the first element of a slice, or null if empty.

lo.first(i32, &.{ 10, 20, 30 }); // 10

last

Returns the last element of a slice, or null if empty.

lo.last(i32, &.{ 10, 20, 30 }); // 30

nth

Element at the given index. Negative indices count from the end. Returns null if out of bounds.

lo.nth(i32, &.{ 10, 20, 30 }, -1); // 30

firstOr

Returns the first element, or a default if the slice is empty.

lo.firstOr(i32, &.{ 10, 20, 30 }, 0); // 10
lo.firstOr(i32, &.{}, 42);             // 42

lastOr

Returns the last element, or a default if the slice is empty.

lo.lastOr(i32, &.{ 10, 20, 30 }, 0); // 30
lo.lastOr(i32, &.{}, 42);             // 42

nthOr

Element at the given index with a default. Negative indices count from the end.

lo.nthOr(i32, &.{ 10, 20, 30 }, 1, 0);  // 20
lo.nthOr(i32, &.{ 10, 20, 30 }, -1, 0); // 30
lo.nthOr(i32, &.{ 10, 20, 30 }, 5, 99); // 99

initial

All elements except the last. Empty slice if input is empty.

lo.initial(i32, &.{ 1, 2, 3 }); // &.{ 1, 2 }

tail

All elements except the first. Empty slice if input is empty.

lo.tail(i32, &.{ 1, 2, 3 }); // &.{ 2, 3 }

drop

Remove the first n elements, returning the rest as a sub-slice.

lo.drop(i32, &.{ 1, 2, 3, 4, 5 }, 2); // &.{ 3, 4, 5 }

dropRight

Remove the last n elements, returning the rest as a sub-slice.

lo.dropRight(i32, &.{ 1, 2, 3, 4, 5 }, 2); // &.{ 1, 2, 3 }

dropWhile

Drop leading elements while the predicate returns true.

lo.dropWhile(i32, &.{ 1, 2, 3, 4 }, isLessThan3); // &.{ 3, 4 }

dropWhileAlloc

Drop leading elements while the predicate returns true. Allocates a copy. Caller owns the returned slice.

const result = try lo.dropWhileAlloc(i32, allocator, &.{ 1, 2, 3, 4 }, isLessThan3);
defer allocator.free(result);
// result == &.{ 3, 4 }

dropRightWhile

Drop trailing elements while the predicate returns true.

lo.dropRightWhile(i32, &.{ 1, 2, 3, 4 }, isGt2); // &.{ 1, 2 }

take

Take the first n elements as a sub-slice.

lo.take(i32, &.{ 1, 2, 3, 4, 5 }, 3); // &.{ 1, 2, 3 }

takeRight

Take the last n elements as a sub-slice.

lo.takeRight(i32, &.{ 1, 2, 3, 4, 5 }, 2); // &.{ 4, 5 }

takeWhile

Take leading elements while the predicate returns true.

lo.takeWhile(i32, &.{ 1, 2, 3, 4 }, isLessThan3); // &.{ 1, 2 }

takeWhileAlloc

Take leading elements while the predicate returns true. Allocates a copy. Caller owns the returned slice.

const result = try lo.takeWhileAlloc(i32, allocator, &.{ 1, 2, 3, 4 }, isLessThan3);
defer allocator.free(result);
// result == &.{ 1, 2 }

takeRightWhile

Take trailing elements while the predicate returns true.

lo.takeRightWhile(i32, &.{ 1, 2, 3, 4 }, isGt2); // &.{ 3, 4 }

sample

Random element from a slice. Null if empty.

var prng = std.Random.DefaultPrng.init(0);
lo.sample(i32, &.{ 1, 2, 3 }, prng.random()); // random element

samples

N random elements from a slice (with replacement). Caller owns the returned slice.

const s = try lo.samples(i32, allocator, &.{ 1, 2, 3 }, 5, rng);
defer allocator.free(s);

Transform

map

Transform each element. Returns a lazy iterator.

var it = lo.map(i32, i64, &.{ 1, 2, 3 }, double);
it.next(); // 2

mapAlloc

Transform each element and collect into an allocated slice. Caller owns the returned slice.

const result = try lo.mapAlloc(i32, i32, allocator, &.{ 1, 2, 3 }, double);
defer allocator.free(result);

mapIndex

Transform each element with its index. Returns a lazy iterator.

var it = lo.mapIndex(i32, i64, &.{ 10, 20 }, addIndex);
it.next(); // addIndex(10, 0)

filter

Keep elements matching the predicate. Returns a lazy iterator.

var it = lo.filter(i32, &.{ 1, 2, 3, 4 }, isEven);
it.next(); // 2
it.next(); // 4

filterAlloc

Keep elements matching the predicate, collected into an allocated slice. Caller owns the returned slice.

const result = try lo.filterAlloc(i32, allocator, &.{ 1, 2, 3, 4 }, isEven);
defer allocator.free(result);

reject

Remove elements matching the predicate. Returns a lazy iterator.

var it = lo.reject(i32, &.{ 1, 2, 3, 4 }, isEven);
it.next(); // 1
it.next(); // 3

rejectAlloc

Remove elements matching the predicate, collected into an allocated slice. Caller owns the returned slice.

const result = try lo.rejectAlloc(i32, allocator, &.{ 1, 2, 3, 4 }, isEven);
defer allocator.free(result);

compact

Remove zero/null/default values. Returns a lazy iterator.

var it = lo.compact(?i32, &.{ 1, null, 3, null });
it.next(); // 1
it.next(); // 3

compactAlloc

Remove zero/null/default values into an allocated slice. Caller owns the returned slice.

const result = try lo.compactAlloc(?i32, allocator, &.{ 1, null, 3 });
defer allocator.free(result);

flatten

Flatten a slice of slices into a single sequence. Returns a lazy iterator.

const data = [_][]const i32{ &.{ 1, 2 }, &.{ 3, 4 } };
var it = lo.flatten(i32, &data);
// yields 1, 2, 3, 4

flattenAlloc

Flatten a slice of slices into an allocated slice. Counts total elements first, then allocates once. Caller owns the returned slice.

const data = [_][]const i32{ &.{ 1, 2 }, &.{ 3, 4, 5 } };
const result = try lo.flattenAlloc(i32, allocator, &data);
defer allocator.free(result);
// result == &.{ 1, 2, 3, 4, 5 }

flattenDeep

Flatten two levels of nesting ([][][]T to []T). Caller owns the returned slice.

const inner = [_][]const i32{ &.{ 1, 2 }, &.{ 3 } };
const outer = [_][]const []const i32{ &inner };
const result = try lo.flattenDeep(i32, allocator, &outer);
defer allocator.free(result);
// result == &.{ 1, 2, 3 }

flatMap

Map each element to a slice, then flatten into a single sequence. Returns a lazy iterator.

var it = lo.flatMap(i32, u8, &.{ 1, 2 }, toDigits);

flatMapAlloc

Map then flatten, collected into an allocated slice. Caller ow

View on GitHub
GitHub Stars31
CategoryDevelopment
Updated4d ago
Forks0

Languages

Zig

Security Score

95/100

Audited on Apr 1, 2026

No findings