Skip to content

sarvensis/dict-picker

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Dict picker (dictionary picker)

Retrieve data from Python dictionaries and lists.

Installation

With pip:

pip install -U dict-picker

Or with conda:

conda install "dict-picker" -c conda-forge

Usage

pick_by_path

The pick_by_path function is used to extract values from nested dictionaries using a path-like string to identify the desired value. The function takes three arguments: a dictionary object, a string representing the path to the desired value and optionally a delimiter.

The path string consists of a sequence of keys, separated by the delimiter character ('/' by default), where each key represents a level in the nested dictionary. If the key has the value '*', it matches any key on that level, or sets it to check all items in the list.

The function returns the value at the end of the path or a list of values if the path contains a wildcard. If the path is not found, the function returns None.

from dict_picker import pick_by_path

example_dict = {
    "foo": "bar",
    "baz": {
        "qux": "quux",
        "quuux": "corge"
    },
    "fred": {
        "wilma": "betty",
        "barney": "pebbles"
    },
    "arr": [
        { 'id': 123 },
        { 'id': 456 },
        { 'id': 789 },
        { 'name': 'bubbles' },
    ],
}

assert pick_by_path(example_dict, "foo") == "bar"
assert pick_by_path(example_dict, "baz/qux") == "quux"
assert pick_by_path(example_dict, "fred/wilma") == "betty"
assert pick_by_path(example_dict, "*/qux") == "quux"
assert pick_by_path(example_dict, "fred/*") == {"wilma": "betty", "barney": "pebbles"}
assert pick_by_path(example_dict, "*/quux") is None
assert pick_by_path(example_dict, "arr/*/id") == [123, 456, 789]

# slice syntax
assert pick_by_path(example_dict, "arr/0") == {'id': 123}
assert pick_by_path(example_dict, "arr/1/id") == 456
assert pick_by_path(example_dict, "arr/-1") == {'name': 'bubbles'}
assert pick_by_path(example_dict, "arr/1:/id") == [456, 789, None]
assert pick_by_path(example_dict, "arr/::-2/id") == [789, 123]

Parameters:

  • obj -- A dictionary object to search for the desired value.
  • path: str -- A string representing the path to the desired value.
  • delimiter: str -- A string used to separate keys in the path string. Default is "/".

Return value:

  • Returns the value found at the end of the path string, or a list of values if the path contains a wildcard. If the path is not found, None is returned.

pick_by_paths

The pick_by_paths function is similar to pick_by_path, but can extract values from multiple paths at once. It takes a dictionary object and a list of path strings as arguments, and returns a list of values found at the end of each path string or None if a path is not found. This works faster than running pick_by_path in a loop.

from dict_picker import pick_by_path, pick_by_paths

example_dict = {
    "foo": "bar",
    "baz": {
        "qux": "quux",
        "quuux": "corge"
    },
    "fred": {
        "wilma": "betty",
        "barney": "pebbles"
    },
    "arr": [
        { 'id': 123 },
        { 'id': 456 },
        { 'id': 789 },
        { 'name': 'bubbles' },
    ],
}

assert pick_by_paths(example_dict, ["fred/*","*/quux", "arr/*/id",]) == [{"wilma": "betty", "barney": "pebbles"}, None, [123, 456, 789]]

Build from sources

Cargo

curl --proto '=https' --tlsv1.2 -sSf <https://sh.rustup.rs> | sh

For other installation options, see the official website.

Maturin

To bind python and rust, pyo3 is used. The Maturin library is used to make it easy to work with.

python -m pip install maturin

Build

python -m maturin build --release

Wheel will be released under the system and python in which it will be built. Read more about the compilation.

The finished wheel can be found in the target/wheels folder.

Build with docker

docker run --rm -v $(pwd):/io ghcr.io/pyo3/maturin build --release  # or other maturin arguments

On macOS, it is better to use docker instead of podman.

Roadmap

  • Arbitrary levels skip operator **;

  • Search inside an array of dictionaries. For example:

    {
        arr:  [
            { id: 123 },
            { id: 456 },
            { id: 789 },
        ]
    }
    'arr/*/id' -> [123, 456, 789]
  • Search by tuple of patterns. Returns the result as a list of found values.

  • add option to access lists via python slice syntax (issue #2):

    {
        arr:  [
            { id: 123 },
            { id: 456 },
            { id: 789 },
        ]
    }
    'arr/1/id' -> 456
    'arr/1' -> { id: 123 }
    'arr/:2/id' -> [123, 456]
    'arr/1:' -> [{ id: 456 },{ id: 789 }]
    'arr/::2/id' -> [123, 789]