py-collections


Namepy-collections JSON
Version 0.1.3 PyPI version JSON
download
home_pageNone
SummaryA Python collections library providing enhanced collection types with additional functionality
upload_time2025-09-07 06:27:01
maintainerNone
docs_urlNone
authorNone
requires_python>=3.13
licenseMIT
keywords collections data-structures dict functional-programming json list mixin python serialization utility
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # py-collections

A Python collections library providing enhanced collection types with additional functionality, built using a modular mixin architecture.

## Development Setup

This project uses [uv](https://github.com/astral-sh/uv) for dependency management and Python environment management.

### Prerequisites

- Python 3.13+
- [uv](https://github.com/astral-sh/uv) installed
- [taskipy](https://github.com/taskipy/taskipy) (optional, for easier command execution)

### Installation

1. Clone the repository
2. Install dependencies:
   ```bash
   uv sync
   ```
3. Install the package in development mode (for running examples):
   ```bash
   uv pip install -e .
   ```

4. (Optional) Install taskipy globally for easier command execution:
   ```bash
   pip install taskipy
   ```

### Running Tests

To run all tests:
```bash
uv run pytest
```

To run tests with verbose output:
```bash
uv run pytest -v
```

To run tests with coverage:
```bash
uv run pytest --cov=src/py_collections --cov-report=term-missing
```

To generate HTML coverage report:
```bash
uv run pytest --cov=src/py_collections --cov-report=html --cov-report=term-missing
```

To run a specific test file:
```bash
uv run pytest tests/core/test_init.py
```

To run tests for a specific mixin:
```bash
uv run pytest tests/mixins/basic_operations/
uv run pytest tests/mixins/transformation/
```

To run tests in watch mode (re-runs on file changes):
```bash
uv run pytest --watch
```

### Development Commands

#### Using taskipy (recommended)
If you have taskipy installed globally (`pip install taskipy`):
- **Install dev dependencies**: `uv sync --group dev`
- **Run linting**: `task check`
- **Format code**: `task format`
- **Check formatting**: `task format-check`
- **Auto-fix linting issues**: `task check-fix`
- **Run tests**: `task test`
- **Run tests with verbose output**: `task test-verbose`
- **Run tests with coverage**: `task test-coverage`
- **Run tests with HTML coverage report**: `task test-coverage-html`
- **Run all checks**: `task lint`
- **Run linting, formatting, and tests**: `task all`

If you don't have taskipy installed globally, use:
- **Run linting**: `uv run python -c "from taskipy import cli; cli.main()" check`
- **Format code**: `uv run python -c "from taskipy import cli; cli.main()" format`
- **Check formatting**: `uv run python -c "from taskipy import cli; cli.main()" format-check`
- **Auto-fix linting issues**: `uv run python -c "from taskipy import cli; cli.main()" check-fix`
- **Run tests**: `uv run python -c "from taskipy import cli; cli.main()" test`
- **Run tests with verbose output**: `uv run python -c "from taskipy import cli; cli.main()" test-verbose`
- **Run tests with coverage**: `uv run python -c "from taskipy import cli; cli.main()" test-coverage`
- **Run tests with HTML coverage report**: `uv run python -c "from taskipy import cli; cli.main()" test-coverage-html`
- **Run all checks**: `uv run python -c "from taskipy import cli; cli.main()" lint`
- **Run linting, formatting, and tests**: `uv run python -c "from taskipy import cli; cli.main()" all`

#### Using uv directly
- **Run linting**: `uv run ruff check .`
- **Format code**: `uv run ruff format .`
- **Type checking**: `uv run mypy src/`
- **Run all checks**: `uv run ruff check . && uv run ruff format --check .`

## Project Structure

```
py-collections/
├── src/py_collections/     # Main package source code
│   ├── collection.py       # Main Collection class (combines all mixins)
│   ├── collection_map.py   # CollectionMap class
│   └── mixins/            # Modular mixin classes
│       ├── basic_operations.py    # append, extend, all, len, iteration
│       ├── element_access.py     # first, last, exists, first_or_raise
│       ├── navigation.py         # after, before
│       ├── transformation.py    # map, pluck, filter, reverse, clone
│       ├── grouping.py          # group_by, chunk
│       ├── removal.py           # remove, remove_one
│       └── utility.py           # take, dump_me, dump_me_and_die
├── tests/                  # Test files organized by functionality
│   ├── core/              # Core Collection tests
│   ├── collection_map/    # CollectionMap tests
│   └── mixins/           # Tests organized by mixin
│       ├── basic_operations/
│       ├── element_access/
│       ├── navigation/
│       ├── transformation/
│       ├── grouping/
│       ├── removal/
│       └── utility/
├── examples/               # Example usage and demonstrations
├── pyproject.toml         # Project configuration and dependencies
└── README.md              # This file
```

## Architecture

The library uses a **mixin-based architecture** to provide modular, maintainable code:

### Mixin Classes

Each mixin provides a focused set of related functionality:

- **BasicOperationsMixin**: Core collection operations (append, extend, all, len, iteration)
- **ElementAccessMixin**: Element retrieval and existence checking (first, last, exists, first_or_raise)
- **NavigationMixin**: Relative element access (after, before)
- **TransformationMixin**: Data transformation operations (map, pluck, filter, reverse, clone)
- **GroupingMixin**: Data grouping and chunking (group_by, chunk)
- **RemovalMixin**: Element removal operations (remove, remove_one)
- **UtilityMixin**: Utility and debugging methods (take, dump_me, dump_me_and_die)

### Benefits of This Architecture

1. **Modularity**: Each mixin focuses on a specific domain of functionality
2. **Maintainability**: Changes to one area don't affect others
3. **Testability**: Tests are organized by functionality
4. **Extensibility**: New functionality can be added as new mixins
5. **Reusability**: Mixins can be used independently if needed

## Features

- Enhanced collection types with additional utility methods
- **Modular mixin architecture** for maintainable code
- Type-safe implementations with full generic support
- **100% test coverage** - All code paths tested
- Modern Python features (3.13+)
- Specialized `CollectionMap` for working with grouped data
- Code quality tools: Ruff (linting + formatting), MyPy (type checking)

## Available Methods

The `Collection` class provides the following methods, organized by mixin:

### Basic Operations (BasicOperationsMixin)
- `append(item)` - Add an item to the collection
- `extend(items)` - Add multiple items from a list or another collection
- `all()` - Get all items as a list
- `len()` - Get the number of items
- **Iteration** - Use in `for` loops and with built-in functions like `sum()`, `max()`, `min()`, `any()`, `all()`, etc.

### Element Access (ElementAccessMixin)
- `first(predicate=None)` - Get the first element (optionally matching a predicate)
- `first_or_raise(predicate=None)` - Get the first element or raise exception if not found
- `last()` - Get the last element
- `exists(predicate=None)` - Check if an element exists (returns boolean)

### Navigation (NavigationMixin)
- `after(target)` - Get the element after a target element or predicate match
- `before(target)` - Get the element before a target element or predicate match

### Transformation (TransformationMixin)
- `filter(predicate)` - Filter elements based on a predicate
- `map(func)` - Apply a function to every item and return a new collection with the results
- `pluck(key, value_key=None)` - Extract values from items based on a key or attribute (inspired by Laravel)
- `reverse()` - Return a new collection with items in reverse order
- `clone()` - Return a new collection with the same items

### Grouping (GroupingMixin)
- `group_by(key)` - Group items by a key or callback function
- `chunk(size)` - Split collection into smaller chunks

### Removal (RemovalMixin)
- `remove(target)` - Remove all items that match the target element or predicate (modifies collection in-place)
- `remove_one(target)` - Remove the first occurrence of an item that matches the target element or predicate (modifies collection in-place)

### Utility (UtilityMixin)
- `take(count)` - Return a new collection with the specified number of items (positive: from beginning, negative: from end)
- `dump_me()` - Debug method to print collection contents (doesn't stop execution)
- `dump_me_and_die()` - Debug method to print collection contents and stop execution
- `to_dict(mode=None)` - Convert items to plain Python structures. With `mode="json"`, ensures JSON-serializable output (datetimes to ISO strings, Decimals to floats, UUIDs to strings, sets to lists, and dict keys to strings)
- `to_json()` - Return a JSON string using `to_dict(mode="json")`

### CollectionMap Class
A specialized map that stores `Collection` instances as values, providing convenient methods for working with grouped data:
- Dictionary-like interface with string keys and Collection values
- Automatic conversion of lists/items to Collection instances
- `get(key)` - Returns empty Collection if key doesn't exist (no KeyError)
- `add(key, items)` - Add items to existing key or create new key
- `flatten()` - Combine all collections into one
- `map(func)` - Apply function to each collection
- `filter(predicate)` - Filter collections based on criteria
- `filter_by_size(min_size, max_size)` - Filter by collection size
- `total_items()` - Get total count across all collections
- `largest_group()` / `smallest_group()` - Find groups by size
- `group_sizes()` - Get size of each group

### Usage Examples

```python
from py_collections import Collection

# Basic usage
numbers = Collection([1, 2, 3, 4, 5])
numbers.append(6)

# Extending with multiple items
numbers.extend([7, 8, 9])
other_numbers = Collection([10, 11, 12])
numbers.extend(other_numbers)

# Reversing the collection
reversed_numbers = numbers.reverse()

# Cloning the collection
cloned_numbers = numbers.clone()  # Create a copy with the same items

# Taking items from the collection
first_two = numbers.take(2)  # Take first 2 items
last_three = numbers.take(-3)  # Take last 3 items

# Mapping elements
doubled = numbers.map(lambda x: x * 2)  # Double each number
squared = numbers.map(lambda x: x ** 2)  # Square each number
strings = numbers.map(str)  # Convert to strings

# Plucking values from objects/dictionaries
users = Collection([{"name": "Alice", "age": 25}, {"name": "Bob", "age": 30}])
names = users.pluck("name")  # ["Alice", "Bob"]
name_age_pairs = users.pluck("name", "age")  # [{"Alice": 25}, {"Bob": 30}]

# Nested key access with dot notation
nested_users = Collection([{"name": "Alice", "address": {"city": "NYC"}}, {"name": "Bob", "address": {"city": "LA"}}])
cities = nested_users.pluck("address.city")  # ["NYC", "LA"]
name_city_pairs = nested_users.pluck("name", "address.city")  # [{"Alice": "NYC"}, {"Bob": "LA"}]

# Removing elements
numbers.remove(1)  # Remove all occurrences of 1
numbers.remove(lambda x: x > 3)  # Remove all elements > 3
numbers.remove_one(lambda x: x == 2)  # Remove first occurrence of 2

# Check if elements exist
if numbers.exists(lambda x: x > 3):
    print("Found number greater than 3")

# Find elements
first_even = numbers.first(lambda x: x % 2 == 0)
after_three = numbers.after(3)

# Filter and chunk
evens = numbers.filter(lambda x: x % 2 == 0)
chunks = numbers.chunk(2)

# Group by
users = Collection([{"name": "Alice", "dept": "Eng"}, {"name": "Bob", "dept": "Sales"}])
by_dept = users.group_by("dept")
by_parity = numbers.group_by(lambda x: "even" if x % 2 == 0 else "odd")

# Iteration
for item in numbers:
    print(item)

# List comprehension
doubled = [item * 2 for item in numbers]

# Built-in functions
total = sum(item for item in numbers)
has_even = any(item % 2 == 0 for item in numbers)

# CollectionMap usage
# Serialization
from py_collections import Collection

data = Collection([
    {"name": "Alice", "age": 30},
    (1, 2, 3),
    {"tags": {"python", "collections"}},
])

# Plain Python structures
structure = data.to_dict()

# JSON-ready structure and JSON string
json_ready = data.to_dict(mode="json")
json_text = data.to_json()

### Pydantic Compatibility
If your items include Pydantic models, they are supported out of the box:

```python
from pydantic import BaseModel
from py_collections import Collection

class User(BaseModel):
    id: int
    name: str

users = Collection([User(id=1, name="Alice"), User(id=2, name="Bob")])

# Converts to list of dicts
users_dict = users.to_dict()

# JSON-ready and stringified
users_json_ready = users.to_dict(mode="json")
users_json = users.to_json()
```

from py_collections import CollectionMap

# Create from group_by result
grouped = users.group_by("department")
cmap = CollectionMap(grouped)

# Work with groups
engineering = cmap["Engineering"]
all_users = cmap.flatten()
group_stats = cmap.map(lambda c: len(c))

# Safe access and incremental building
missing = cmap.get("missing")  # Returns empty Collection
cmap.add("new_group", [1, 2, 3])  # Creates new group
cmap.add("existing_group", [4, 5])  # Extends existing group

## Contributing

1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests for new functionality
5. Run tests: `uv run pytest`
6. Submit a pull request

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "py-collections",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.13",
    "maintainer_email": "Matias Gallardo <10453322+mato777@users.noreply.github.com>",
    "keywords": "collections, data-structures, dict, functional-programming, json, list, mixin, python, serialization, utility",
    "author": null,
    "author_email": "Matias Gallardo <10453322+mato777@users.noreply.github.com>",
    "download_url": "https://files.pythonhosted.org/packages/27/76/9eaf73ad44f71eae55a8dadd8e401467721ba2e8e33252eec96cfcbf8033/py_collections-0.1.3.tar.gz",
    "platform": null,
    "description": "# py-collections\n\nA Python collections library providing enhanced collection types with additional functionality, built using a modular mixin architecture.\n\n## Development Setup\n\nThis project uses [uv](https://github.com/astral-sh/uv) for dependency management and Python environment management.\n\n### Prerequisites\n\n- Python 3.13+\n- [uv](https://github.com/astral-sh/uv) installed\n- [taskipy](https://github.com/taskipy/taskipy) (optional, for easier command execution)\n\n### Installation\n\n1. Clone the repository\n2. Install dependencies:\n   ```bash\n   uv sync\n   ```\n3. Install the package in development mode (for running examples):\n   ```bash\n   uv pip install -e .\n   ```\n\n4. (Optional) Install taskipy globally for easier command execution:\n   ```bash\n   pip install taskipy\n   ```\n\n### Running Tests\n\nTo run all tests:\n```bash\nuv run pytest\n```\n\nTo run tests with verbose output:\n```bash\nuv run pytest -v\n```\n\nTo run tests with coverage:\n```bash\nuv run pytest --cov=src/py_collections --cov-report=term-missing\n```\n\nTo generate HTML coverage report:\n```bash\nuv run pytest --cov=src/py_collections --cov-report=html --cov-report=term-missing\n```\n\nTo run a specific test file:\n```bash\nuv run pytest tests/core/test_init.py\n```\n\nTo run tests for a specific mixin:\n```bash\nuv run pytest tests/mixins/basic_operations/\nuv run pytest tests/mixins/transformation/\n```\n\nTo run tests in watch mode (re-runs on file changes):\n```bash\nuv run pytest --watch\n```\n\n### Development Commands\n\n#### Using taskipy (recommended)\nIf you have taskipy installed globally (`pip install taskipy`):\n- **Install dev dependencies**: `uv sync --group dev`\n- **Run linting**: `task check`\n- **Format code**: `task format`\n- **Check formatting**: `task format-check`\n- **Auto-fix linting issues**: `task check-fix`\n- **Run tests**: `task test`\n- **Run tests with verbose output**: `task test-verbose`\n- **Run tests with coverage**: `task test-coverage`\n- **Run tests with HTML coverage report**: `task test-coverage-html`\n- **Run all checks**: `task lint`\n- **Run linting, formatting, and tests**: `task all`\n\nIf you don't have taskipy installed globally, use:\n- **Run linting**: `uv run python -c \"from taskipy import cli; cli.main()\" check`\n- **Format code**: `uv run python -c \"from taskipy import cli; cli.main()\" format`\n- **Check formatting**: `uv run python -c \"from taskipy import cli; cli.main()\" format-check`\n- **Auto-fix linting issues**: `uv run python -c \"from taskipy import cli; cli.main()\" check-fix`\n- **Run tests**: `uv run python -c \"from taskipy import cli; cli.main()\" test`\n- **Run tests with verbose output**: `uv run python -c \"from taskipy import cli; cli.main()\" test-verbose`\n- **Run tests with coverage**: `uv run python -c \"from taskipy import cli; cli.main()\" test-coverage`\n- **Run tests with HTML coverage report**: `uv run python -c \"from taskipy import cli; cli.main()\" test-coverage-html`\n- **Run all checks**: `uv run python -c \"from taskipy import cli; cli.main()\" lint`\n- **Run linting, formatting, and tests**: `uv run python -c \"from taskipy import cli; cli.main()\" all`\n\n#### Using uv directly\n- **Run linting**: `uv run ruff check .`\n- **Format code**: `uv run ruff format .`\n- **Type checking**: `uv run mypy src/`\n- **Run all checks**: `uv run ruff check . && uv run ruff format --check .`\n\n## Project Structure\n\n```\npy-collections/\n\u251c\u2500\u2500 src/py_collections/     # Main package source code\n\u2502   \u251c\u2500\u2500 collection.py       # Main Collection class (combines all mixins)\n\u2502   \u251c\u2500\u2500 collection_map.py   # CollectionMap class\n\u2502   \u2514\u2500\u2500 mixins/            # Modular mixin classes\n\u2502       \u251c\u2500\u2500 basic_operations.py    # append, extend, all, len, iteration\n\u2502       \u251c\u2500\u2500 element_access.py     # first, last, exists, first_or_raise\n\u2502       \u251c\u2500\u2500 navigation.py         # after, before\n\u2502       \u251c\u2500\u2500 transformation.py    # map, pluck, filter, reverse, clone\n\u2502       \u251c\u2500\u2500 grouping.py          # group_by, chunk\n\u2502       \u251c\u2500\u2500 removal.py           # remove, remove_one\n\u2502       \u2514\u2500\u2500 utility.py           # take, dump_me, dump_me_and_die\n\u251c\u2500\u2500 tests/                  # Test files organized by functionality\n\u2502   \u251c\u2500\u2500 core/              # Core Collection tests\n\u2502   \u251c\u2500\u2500 collection_map/    # CollectionMap tests\n\u2502   \u2514\u2500\u2500 mixins/           # Tests organized by mixin\n\u2502       \u251c\u2500\u2500 basic_operations/\n\u2502       \u251c\u2500\u2500 element_access/\n\u2502       \u251c\u2500\u2500 navigation/\n\u2502       \u251c\u2500\u2500 transformation/\n\u2502       \u251c\u2500\u2500 grouping/\n\u2502       \u251c\u2500\u2500 removal/\n\u2502       \u2514\u2500\u2500 utility/\n\u251c\u2500\u2500 examples/               # Example usage and demonstrations\n\u251c\u2500\u2500 pyproject.toml         # Project configuration and dependencies\n\u2514\u2500\u2500 README.md              # This file\n```\n\n## Architecture\n\nThe library uses a **mixin-based architecture** to provide modular, maintainable code:\n\n### Mixin Classes\n\nEach mixin provides a focused set of related functionality:\n\n- **BasicOperationsMixin**: Core collection operations (append, extend, all, len, iteration)\n- **ElementAccessMixin**: Element retrieval and existence checking (first, last, exists, first_or_raise)\n- **NavigationMixin**: Relative element access (after, before)\n- **TransformationMixin**: Data transformation operations (map, pluck, filter, reverse, clone)\n- **GroupingMixin**: Data grouping and chunking (group_by, chunk)\n- **RemovalMixin**: Element removal operations (remove, remove_one)\n- **UtilityMixin**: Utility and debugging methods (take, dump_me, dump_me_and_die)\n\n### Benefits of This Architecture\n\n1. **Modularity**: Each mixin focuses on a specific domain of functionality\n2. **Maintainability**: Changes to one area don't affect others\n3. **Testability**: Tests are organized by functionality\n4. **Extensibility**: New functionality can be added as new mixins\n5. **Reusability**: Mixins can be used independently if needed\n\n## Features\n\n- Enhanced collection types with additional utility methods\n- **Modular mixin architecture** for maintainable code\n- Type-safe implementations with full generic support\n- **100% test coverage** - All code paths tested\n- Modern Python features (3.13+)\n- Specialized `CollectionMap` for working with grouped data\n- Code quality tools: Ruff (linting + formatting), MyPy (type checking)\n\n## Available Methods\n\nThe `Collection` class provides the following methods, organized by mixin:\n\n### Basic Operations (BasicOperationsMixin)\n- `append(item)` - Add an item to the collection\n- `extend(items)` - Add multiple items from a list or another collection\n- `all()` - Get all items as a list\n- `len()` - Get the number of items\n- **Iteration** - Use in `for` loops and with built-in functions like `sum()`, `max()`, `min()`, `any()`, `all()`, etc.\n\n### Element Access (ElementAccessMixin)\n- `first(predicate=None)` - Get the first element (optionally matching a predicate)\n- `first_or_raise(predicate=None)` - Get the first element or raise exception if not found\n- `last()` - Get the last element\n- `exists(predicate=None)` - Check if an element exists (returns boolean)\n\n### Navigation (NavigationMixin)\n- `after(target)` - Get the element after a target element or predicate match\n- `before(target)` - Get the element before a target element or predicate match\n\n### Transformation (TransformationMixin)\n- `filter(predicate)` - Filter elements based on a predicate\n- `map(func)` - Apply a function to every item and return a new collection with the results\n- `pluck(key, value_key=None)` - Extract values from items based on a key or attribute (inspired by Laravel)\n- `reverse()` - Return a new collection with items in reverse order\n- `clone()` - Return a new collection with the same items\n\n### Grouping (GroupingMixin)\n- `group_by(key)` - Group items by a key or callback function\n- `chunk(size)` - Split collection into smaller chunks\n\n### Removal (RemovalMixin)\n- `remove(target)` - Remove all items that match the target element or predicate (modifies collection in-place)\n- `remove_one(target)` - Remove the first occurrence of an item that matches the target element or predicate (modifies collection in-place)\n\n### Utility (UtilityMixin)\n- `take(count)` - Return a new collection with the specified number of items (positive: from beginning, negative: from end)\n- `dump_me()` - Debug method to print collection contents (doesn't stop execution)\n- `dump_me_and_die()` - Debug method to print collection contents and stop execution\n- `to_dict(mode=None)` - Convert items to plain Python structures. With `mode=\"json\"`, ensures JSON-serializable output (datetimes to ISO strings, Decimals to floats, UUIDs to strings, sets to lists, and dict keys to strings)\n- `to_json()` - Return a JSON string using `to_dict(mode=\"json\")`\n\n### CollectionMap Class\nA specialized map that stores `Collection` instances as values, providing convenient methods for working with grouped data:\n- Dictionary-like interface with string keys and Collection values\n- Automatic conversion of lists/items to Collection instances\n- `get(key)` - Returns empty Collection if key doesn't exist (no KeyError)\n- `add(key, items)` - Add items to existing key or create new key\n- `flatten()` - Combine all collections into one\n- `map(func)` - Apply function to each collection\n- `filter(predicate)` - Filter collections based on criteria\n- `filter_by_size(min_size, max_size)` - Filter by collection size\n- `total_items()` - Get total count across all collections\n- `largest_group()` / `smallest_group()` - Find groups by size\n- `group_sizes()` - Get size of each group\n\n### Usage Examples\n\n```python\nfrom py_collections import Collection\n\n# Basic usage\nnumbers = Collection([1, 2, 3, 4, 5])\nnumbers.append(6)\n\n# Extending with multiple items\nnumbers.extend([7, 8, 9])\nother_numbers = Collection([10, 11, 12])\nnumbers.extend(other_numbers)\n\n# Reversing the collection\nreversed_numbers = numbers.reverse()\n\n# Cloning the collection\ncloned_numbers = numbers.clone()  # Create a copy with the same items\n\n# Taking items from the collection\nfirst_two = numbers.take(2)  # Take first 2 items\nlast_three = numbers.take(-3)  # Take last 3 items\n\n# Mapping elements\ndoubled = numbers.map(lambda x: x * 2)  # Double each number\nsquared = numbers.map(lambda x: x ** 2)  # Square each number\nstrings = numbers.map(str)  # Convert to strings\n\n# Plucking values from objects/dictionaries\nusers = Collection([{\"name\": \"Alice\", \"age\": 25}, {\"name\": \"Bob\", \"age\": 30}])\nnames = users.pluck(\"name\")  # [\"Alice\", \"Bob\"]\nname_age_pairs = users.pluck(\"name\", \"age\")  # [{\"Alice\": 25}, {\"Bob\": 30}]\n\n# Nested key access with dot notation\nnested_users = Collection([{\"name\": \"Alice\", \"address\": {\"city\": \"NYC\"}}, {\"name\": \"Bob\", \"address\": {\"city\": \"LA\"}}])\ncities = nested_users.pluck(\"address.city\")  # [\"NYC\", \"LA\"]\nname_city_pairs = nested_users.pluck(\"name\", \"address.city\")  # [{\"Alice\": \"NYC\"}, {\"Bob\": \"LA\"}]\n\n# Removing elements\nnumbers.remove(1)  # Remove all occurrences of 1\nnumbers.remove(lambda x: x > 3)  # Remove all elements > 3\nnumbers.remove_one(lambda x: x == 2)  # Remove first occurrence of 2\n\n# Check if elements exist\nif numbers.exists(lambda x: x > 3):\n    print(\"Found number greater than 3\")\n\n# Find elements\nfirst_even = numbers.first(lambda x: x % 2 == 0)\nafter_three = numbers.after(3)\n\n# Filter and chunk\nevens = numbers.filter(lambda x: x % 2 == 0)\nchunks = numbers.chunk(2)\n\n# Group by\nusers = Collection([{\"name\": \"Alice\", \"dept\": \"Eng\"}, {\"name\": \"Bob\", \"dept\": \"Sales\"}])\nby_dept = users.group_by(\"dept\")\nby_parity = numbers.group_by(lambda x: \"even\" if x % 2 == 0 else \"odd\")\n\n# Iteration\nfor item in numbers:\n    print(item)\n\n# List comprehension\ndoubled = [item * 2 for item in numbers]\n\n# Built-in functions\ntotal = sum(item for item in numbers)\nhas_even = any(item % 2 == 0 for item in numbers)\n\n# CollectionMap usage\n# Serialization\nfrom py_collections import Collection\n\ndata = Collection([\n    {\"name\": \"Alice\", \"age\": 30},\n    (1, 2, 3),\n    {\"tags\": {\"python\", \"collections\"}},\n])\n\n# Plain Python structures\nstructure = data.to_dict()\n\n# JSON-ready structure and JSON string\njson_ready = data.to_dict(mode=\"json\")\njson_text = data.to_json()\n\n### Pydantic Compatibility\nIf your items include Pydantic models, they are supported out of the box:\n\n```python\nfrom pydantic import BaseModel\nfrom py_collections import Collection\n\nclass User(BaseModel):\n    id: int\n    name: str\n\nusers = Collection([User(id=1, name=\"Alice\"), User(id=2, name=\"Bob\")])\n\n# Converts to list of dicts\nusers_dict = users.to_dict()\n\n# JSON-ready and stringified\nusers_json_ready = users.to_dict(mode=\"json\")\nusers_json = users.to_json()\n```\n\nfrom py_collections import CollectionMap\n\n# Create from group_by result\ngrouped = users.group_by(\"department\")\ncmap = CollectionMap(grouped)\n\n# Work with groups\nengineering = cmap[\"Engineering\"]\nall_users = cmap.flatten()\ngroup_stats = cmap.map(lambda c: len(c))\n\n# Safe access and incremental building\nmissing = cmap.get(\"missing\")  # Returns empty Collection\ncmap.add(\"new_group\", [1, 2, 3])  # Creates new group\ncmap.add(\"existing_group\", [4, 5])  # Extends existing group\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch\n3. Make your changes\n4. Add tests for new functionality\n5. Run tests: `uv run pytest`\n6. Submit a pull request\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A Python collections library providing enhanced collection types with additional functionality",
    "version": "0.1.3",
    "project_urls": {
        "Bug Tracker": "https://github.com/mato777/py-collections/issues",
        "Documentation": "https://github.com/mato777/py-collections#readme",
        "Homepage": "https://github.com/mato777/py-collections",
        "Repository": "https://github.com/mato777/py-collections",
        "Source Code": "https://github.com/mato777/py-collections"
    },
    "split_keywords": [
        "collections",
        " data-structures",
        " dict",
        " functional-programming",
        " json",
        " list",
        " mixin",
        " python",
        " serialization",
        " utility"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "d2bccc566ce5e320cfa101d2aaeb5a1b9358badc27a3ca31d0c87e3cb0a60166",
                "md5": "8e58c01fedacdb78709ac0da6f01b805",
                "sha256": "b9469a8a412919ee65de844be30ea7053e9984c366b75b2bfa4cc34eefdd9d1a"
            },
            "downloads": -1,
            "filename": "py_collections-0.1.3-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "8e58c01fedacdb78709ac0da6f01b805",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.13",
            "size": 19790,
            "upload_time": "2025-09-07T06:27:00",
            "upload_time_iso_8601": "2025-09-07T06:27:00.245795Z",
            "url": "https://files.pythonhosted.org/packages/d2/bc/cc566ce5e320cfa101d2aaeb5a1b9358badc27a3ca31d0c87e3cb0a60166/py_collections-0.1.3-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "27769eaf73ad44f71eae55a8dadd8e401467721ba2e8e33252eec96cfcbf8033",
                "md5": "60756df8776819f2637c7a36d51a2323",
                "sha256": "5e3a84dde4eb1b19d509d73ffd9d1fea3445b1191be2f4f6f124e8ca2aa7e842"
            },
            "downloads": -1,
            "filename": "py_collections-0.1.3.tar.gz",
            "has_sig": false,
            "md5_digest": "60756df8776819f2637c7a36d51a2323",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.13",
            "size": 79420,
            "upload_time": "2025-09-07T06:27:01",
            "upload_time_iso_8601": "2025-09-07T06:27:01.244308Z",
            "url": "https://files.pythonhosted.org/packages/27/76/9eaf73ad44f71eae55a8dadd8e401467721ba2e8e33252eec96cfcbf8033/py_collections-0.1.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-09-07 06:27:01",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "mato777",
    "github_project": "py-collections",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "py-collections"
}
        
Elapsed time: 1.59740s