omegaalfa/collection

This library implements the Trie routing logic

Installs: 13

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 1

Forks: 0

Open Issues: 0

pkg:composer/omegaalfa/collection

v1.0.0 2026-01-01 17:49 UTC

This package is not auto-updated.

Last update: 2026-01-01 17:50:33 UTC


README

πŸš€ PHP Collection Library

PHP Version License Tests Coverage PHPStan

A powerful, type-safe PHP collection library with eager & lazy evaluation 🎯

Features β€’ Installation β€’ Quick Start β€’ Documentation β€’ Examples

✨ Features

🎯 Type-Safe

Full PHPDoc generics support

Sequence<User>
Map<string, Config>

⚑ Lazy Evaluation

Memory-efficient processing

LazySequence::range(1, 1M)
  ->take(10) // Only 10 iterations!

πŸ”’ Immutable

Readonly data structures

$new = $seq->append(42);
// Original unchanged
  • βœ… 7 Specialized Classes - Collection, Sequence, Map, LazySequence, LazyMap, LazyFileIterator, LazyProxyObject
  • βœ… 150+ Methods - Rich API with fluent interface
  • βœ… Modern PHP - PHP 8.3+ with strict types & readonly properties
  • βœ… Well Tested - 239 tests, 80.85% coverage
  • βœ… Zero Dependencies - Pure PHP, no external packages required

πŸ“¦ Installation

composer require omegaalfa/collection

Requirements

Requirement Version Note
PHP >= 8.3 Required
PHP >= 8.4 Recommended for LazyProxyObject

🎯 Core Concepts

Class Type Purpose Use Case
Collection Generic Iterator wrapper with transformations βœ… Mixed data, legacy code, Iterator support
Sequence Eager Ordered immutable list βœ… Small lists, type safety, immutability
Map Eager Immutable key-value dictionary βœ… Small maps, type safety, immutability
LazySequence Lazy Generator-based pipeline βœ… Large datasets, streaming, memory efficiency
LazyMap Lazy Lazy value computation βœ… Expensive computations, caching, DI
LazyFileIterator Lazy File streaming (JSON lines) βœ… Large files, memory constraints
LazyProxyObject Lazy PHP 8.4+ lazy object instantiation βœ… Expensive objects, service containers

οΏ½ Quick Start

πŸ’‘ Collection - Generic Wrapper

Click to expand
use Omegaalfa\Collection\Collection;

// Create from array or Iterator
$collection = new Collection([1, 2, 3, 4, 5]);

// Transform (eager)
$doubled = $collection->map(fn($x) => $x * 2);
$evens = $collection->filter(fn($x) => $x % 2 === 0);

// πŸš€ Lazy methods (memory efficient!)
$result = Collection::lazyRange(1, 1000000)
    ->lazyMap(fn($x) => $x * 2)
    ->lazyFilter(fn($x) => $x > 100)
    ->lazyTake(10);  // Only processes ~51 elements!

// Array access
$collection['key'] = 'value';
echo $collection['key'];

// Statistics
echo $collection->sum();    // 15
echo $collection->avg();    // 3
echo $collection->count();  // 5

πŸ“‹ Sequence - Ordered Immutable List

Click to expand
use Omegaalfa\Collection\Sequence;

// Create
$numbers = Sequence::of(1, 2, 3, 4, 5);
$range = Sequence::range(1, 10);

// Immutable transformations
$doubled = $numbers->map(fn($x) => $x * 2);
$evens = $numbers->filter(fn($x) => $x % 2 === 0);

// πŸ”— Fluent chaining
$result = Sequence::range(1, 100)
    ->filter(fn($x) => $x % 3 === 0)
    ->map(fn($x) => $x * $x)
    ->take(5);

// Access
echo $numbers->at(0);      // 1
echo $numbers->first();    // 1
echo $numbers->last();     // 5

// Operations (returns new Sequence)
$appended = $numbers->append(6);
$prepended = $numbers->prepend(0);
$inserted = $numbers->insert(2, 99);
$removed = $numbers->remove(2);

πŸ—ΊοΈ Map - Immutable Key-Value Dictionary

Click to expand
use Omegaalfa\Collection\Map;

// Create
$user = Map::of(
    'name', 'John',
    'age', 30,
    'city', 'NY'
);

// Access
echo $user->get('name');               // John
echo $user->getOrDefault('email', '-'); // -

// Transform (returns new Map)
$aged = $user->put('age', 31);
$removed = $user->remove('city');

// πŸ”„ Transformations
$uppercased = $user->mapValues(fn($k, $v) => is_string($v) ? strtoupper($v) : $v);
$prefixed = $user->mapKeys(fn($k) => "user_$k");

// Merge
$merged = $user->merge(Map::of('email', 'john@example.com'));

⚑ LazySequence - Generator-Based Pipeline

Click to expand
use Omegaalfa\Collection\LazySequence;

// πŸš€ Pipeline - NOTHING executes until iteration!
$pipeline = LazySequence::range(1, 1000000)
    ->map(fn($x) => $x * 2)
    ->filter(fn($x) => $x > 100)
    ->take(10);

// Now it executes - only ~51 iterations!
foreach ($pipeline as $value) {
    echo $value;  // 102, 104, 106...
}

// ⚑ Short-circuit operations
$first = LazySequence::range(1, 1000000)->first();  // Stops at 1

// Materialize to eager
$eager = $lazy->toEager();  // Returns Sequence

🎯 LazyMap - Lazy Value Computation

Click to expand
use Omegaalfa\Collection\LazyMap;

// Values are closures - computed on-demand! πŸ’‘
$config = LazyMap::from([
    'database' => fn() => new Database(),  // Not created yet
    'cache' => fn() => new Redis(),        // Not created yet
    'api' => fn() => new ApiClient()       // Not created yet
]);

// ⚑ Only creates Database when accessed
$db = $config->get('database');

// πŸ†• With LazyProxyObject (PHP 8.4+)
$services = LazyMap::ofLazyObjects([
    'logger' => [Logger::class, $config],
    'mailer' => [Mailer::class, $smtp]
]);

// Creates lazy proxy - object instantiated on first method call
$logger = $services->get('logger');
$logger->info('message');  // NOW Logger is instantiated

πŸ“ LazyFileIterator - Stream Large Files

Click to expand
use Omegaalfa\Collection\LazyFileIterator;

// πŸ“„ Stream JSON lines file (memory efficient!)
$iterator = new LazyFileIterator('data.jsonl');

foreach ($iterator as $index => $object) {
    echo "Line {$index}: {$object->name}\n";
}

// Use with Collection for transformations
$collection = new Collection($iterator);
$filtered = $collection->lazyFilter(fn($obj) => $obj->active);

🎯 Choosing the Right Class

Use Collection πŸ’‘

  • βœ… Working with Iterator instances
  • βœ… Need array-like access (ArrayAccess)
  • βœ… Want both eager and lazy methods
  • βœ… Migrating legacy code

Use Sequence πŸ“‹

  • βœ… Need ordered list (0-indexed)
  • βœ… Want immutability
  • βœ… Working with small-to-medium datasets
  • βœ… Type safety is important

Use Map πŸ—ΊοΈ

  • βœ… Need key-value pairs
  • βœ… Want immutability
  • βœ… Working with configuration, dictionaries
  • βœ… Type safety is important

Use LazySequence ⚑

  • βœ… Large datasets (millions of items)
  • βœ… Memory is constrained
  • βœ… Need pipeline composition
  • βœ… Can benefit from short-circuit evaluation

Use LazyMap 🎯

  • βœ… Values are expensive to compute
  • βœ… Not all values will be accessed
  • βœ… Need lazy initialization
  • βœ… Dependency injection containers

Use LazyFileIterator πŸ“

  • βœ… Processing large JSON line files
  • βœ… Cannot load entire file in memory
  • βœ… Streaming data processing

οΏ½ API Reference

πŸ”₯ Core Methods - Quick Reference

πŸ”„ Transformation

map(callable $fn): self           // Transform each element
filter(callable $fn): self        // Keep matching elements
flatMap(callable $fn): self       // Map + flatten
reduce(callable $fn, mixed $init) // Reduce to single value

πŸ“Š Aggregation

sum(): int|float                  // Sum all numeric values
avg(): int|float                  // Calculate average
min(): mixed                      // Find minimum
max(): mixed                      // Find maximum
count(): int                      // Count elements

πŸ” Retrieval

first(): mixed                    // Get first element
last(): mixed                     // Get last element
find(callable $fn): mixed         // Find matching element
any(callable $fn): bool           // Check if any matches
all(callable $fn): bool           // Check if all match

⚑ Lazy Operations

take(int $n): self               // Take first n elements
skip(int $n): self               // Skip first n elements
chunk(int $size): self           // Split into chunks
takeWhile(callable $fn): self    // Take while predicate true
skipWhile(callable $fn): self    // Skip while predicate true
πŸ“‹ Full Method Compatibility Matrix
Method Collection Sequence Map LazySequence LazyMap
map βœ… βœ… βœ… βœ… βœ…
filter βœ… βœ… βœ… βœ… βœ…
reduce βœ… βœ… βœ… βœ… βœ…
take βœ… βœ… βœ… βœ… βœ…
skip βœ… βœ… βœ… βœ… βœ…
chunk βœ… βœ… βœ… βœ… βœ…
sort βœ… βœ… ❌ βœ… ❌
reverse βœ… βœ… ❌ βœ… ❌
unique βœ… βœ… ❌ βœ… ❌
merge βœ… βœ… βœ… βœ… βœ…
keys βœ… ❌ βœ… ❌ βœ…
values βœ… βœ… βœ… βœ… βœ…
mapKeys ❌ ❌ βœ… ❌ βœ…
mapValues ❌ ❌ βœ… ❌ βœ…

πŸ“– Complete documentation: docs/API.md β€’ 150+ methods documented

⚑ Performance & Optimization

πŸ’Ύ Memory Efficiency

Traditional Approach ❌

// Processes 1M elements
$data = range(1, 1000000);
$result = array_map(
    fn($x) => $x * 2,
    array_filter($data, fn($x) => $x % 2 === 0)
);

Result: ~400 MB | ~850ms

Lazy Evaluation βœ…

// Only processes 51 elements!
$result = LazySequence::range(1, 1000000)
    ->map(fn($x) => $x * 2)
    ->filter(fn($x) => $x > 100)
    ->take(10);

Result: ~2 MB | ~0.7ms
πŸš€ 2290x FASTER!

πŸ“Š Benchmark Results

View Detailed Benchmarks
πŸ“Š Processing 1,000,000 items:

Traditional Array:        ~400 MB peak | ~850ms
Collection (eager):       ~380 MB peak | ~820ms
LazySequence:            ~2 MB peak   | ~12ms   ⚑ 70x faster
LazyFileIterator:        ~1 MB peak   | ~8ms    ⚑ 106x faster

Operation: map β†’ filter β†’ take(100)

Implementation Time Memory vs Array
Array 850ms 400 MB baseline
Collection 820ms 380 MB 1.04x faster
LazySequence 12ms 2 MB 70x faster
LazyFileIterator 8ms 1 MB 106x faster

🎯 Lazy vs Eager Trade-offs

Scenario Use Lazy ⚑ Use Eager πŸƒ
Large datasets (100k+) βœ… Memory efficient ❌ High memory
Expensive operations βœ… Deferred execution ❌ Upfront cost
Short-circuit (take, first) βœ… Early termination ❌ Full processing
Multiple transformations βœ… Single-pass ❌ Multiple passes
Small datasets (<1k) ❌ Overhead βœ… Fast
Random access ❌ Must materialize βœ… Direct access

πŸ” Detailed analysis: docs/PROFILING_ANALYSIS.md

πŸ§ͺ Testing

# Run all tests
composer test

# Run with coverage report
composer test:coverage

# Static analysis (PHPStan level 9)
composer phpstan

πŸ“Š Code Quality Metrics

Metric Value Status
Tests 239 tests βœ…
Assertions 374 assertions βœ…
Line Coverage 80.85% βœ…
Method Coverage 76.92% βœ…
PHPStan Level Max (9) βœ…

πŸ“– Documentation

πŸ“˜ Core Documentation

πŸ’‘ Examples & Guides

πŸ† Benchmark

Run the included benchmark script:

php benchmark.php
Sample Output
🎯 Collection Library Benchmark
================================

πŸ“Š Test: map + filter + take(100) on 1,000,000 items

βœ… Traditional Array:     850ms  |  400 MB
βœ… Collection (eager):    820ms  |  380 MB
βœ… LazySequence:          12ms   |  2 MB    πŸš€ 70x faster
βœ… LazyFileIterator:      8ms    |  1 MB    πŸš€ 106x faster

πŸ’‘ Winner: LazyFileIterator
   - 106x faster
   - 400x less memory
   - Perfect for streaming large datasets

πŸ—οΈ Architecture

πŸ“ Class Hierarchy & Design Patterns
Contract/
β”œβ”€β”€ MapInterface           # Contract for Map implementations
└── SequenceInterface      # Contract for Sequence implementations

Traits/
β”œβ”€β”€ CollectionTransformationsTrait  # Transformation operations
β”œβ”€β”€ CollectionAggregatesTrait       # Aggregation operations
β”œβ”€β”€ CollectionArrayAccessTrait      # ArrayAccess implementation
└── LazyOperationsTrait             # Lazy evaluation operations

Core Classes/
β”œβ”€β”€ Collection             # Hybrid: Eager + Lazy operations
β”œβ”€β”€ Sequence              # Immutable ordered list
β”œβ”€β”€ Map                   # Immutable key-value map
β”œβ”€β”€ LazySequence          # Generator-based lazy sequence
└── LazyMap               # Lazy-evaluated map (Closures)

Utilities/
β”œβ”€β”€ LazyProxyObject       # PHP 8.4+ lazy object proxies
└── LazyFileIterator      # Stream large files efficiently

File Parsers/
β”œβ”€β”€ ParserInterface
β”œβ”€β”€ JsonLinesParser       # Parse .jsonl files
β”œβ”€β”€ CsvParser             # Parse CSV files
β”œβ”€β”€ TsvParser             # Parse TSV files
└── PlainTextParser       # Parse plain text

🎨 Design Principles

βœ… Core Principles

  • Immutability: All transformations return new instances
  • Lazy Evaluation: Defer computation until needed
  • Type Safety: Full PHPDoc generics support
  • Interface Contracts: Clear API boundaries

🌟 Inspired By

πŸ“„ License

This project is licensed under the MIT License
See the LICENSE file for details

Permission is hereby granted, free of charge, to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software.

🀝 Contributing

Contributions are welcome! πŸŽ‰

πŸ“ How to Contribute

  1. 🍴 Fork the repository
  2. 🌿 Create a feature branch
    git checkout -b feature/amazing-feature
  3. βœ… Ensure all tests pass
    composer test
    composer phpstan
  4. πŸ“ Commit your changes
    git commit -m 'feat: add amazing feature'
  5. πŸ“€ Push to the branch
    git push origin feature/amazing-feature
  6. πŸŽ‰ Open a Pull Request

πŸ“‹ Contribution Guidelines

Requirement Description
βœ… Tests All tests must pass (composer test)
βœ… PHPStan Level 9 compliance required
βœ… Coverage Maintain >75% code coverage
βœ… PSR-12 Follow PHP coding standards
βœ… Conventional Commits Use semantic commit messages

πŸ’¬ Support & Community

Channel Link Description
πŸ› Issues GitHub Issues Bug reports & feature requests
πŸ’‘ Discussions GitHub Discussions Questions & ideas
πŸ“§ Email support@omegaalfa.dev Direct support
πŸ“– Docs Documentation Complete guides

⭐ Star History

Star History Chart

Made with ❀️ by the Omegaalfa Team

⭐ Star this repo if you find it useful!

πŸ“– Documentation β€’ πŸ’‘ Examples β€’ πŸ“ Changelog β€’ πŸ“„ License