Skip to main content

pylookups

Excel-style lookup, filter, and sort functions for plain Python lists — no pandas or numpy required.

Docs: https://lalit2206.github.io/pylookups/

pip install pylookups

The install name is pylookups, but the import name is pylookup:

from pylookup import vlookup, xlookup, match, index, index_match, filter, unique, sort, join, read_table

Note: filter shadows Python's built-in filter in any module that imports it by name. If you still need the built-in in the same file, use the namespaced style instead:

import pylookup as pl

pl.filter([1, 2, 3, 4], lambda x: x > 2)

Install (local development)

python -m venv .venv
.venv\Scripts\activate        # Windows
pip install -e ".[dev]"
pytest

Functions

Row/column positions follow Excel's convention: 1-based, not 0-based.

match(lookup_value, lookup_array, match_type=0)

Position (1-based) of lookup_value in lookup_array. match_type: 0 exact, 1 largest value <= target (ascending array), -1 smallest value >= target (descending array). Raises NotFoundError.

index(array, row_num, col_num=None)

Value at row_num (and col_num for a 2D table). Omit col_num to get the whole row.

index_match(return_array, lookup_value, lookup_array, match_type=0)

index + match combined: find lookup_value in lookup_array, return the item at that position in return_array.

vlookup(lookup_value, table, col_index=None, exact=True, if_not_found=...)

Search the first column of table (list of rows) for lookup_value, then return something from the matching row. col_index can be a 1-based number, a column name ("score"), a list of either, or None for the whole row. Using a name treats the first row as a header.

hlookup(lookup_value, table, row_index=None, exact=True, if_not_found=...)

The same thing sideways: search the first row of table, return from the matching column. row_index accepts a number, a row label, a list, or None.

join(left, right, by, if_not_found=None)

Attach every column of right to the rows of left that share a key — "drag the VLOOKUP down the column", as one call. by is a shared column name, a (left_key, right_key) pair, or a 1-based number. Unmatched rows are kept and filled with if_not_found.

xlookup(lookup_value, lookup_array, return_array, if_not_found=..., match_mode=0, search_mode=1)

Search lookup_array for lookup_value, return the corresponding item from return_array. match_mode: 0 exact, -1 exact or next smaller, 1 exact or next larger. search_mode: 1 first-to-last, -1 last-to-first. Pass if_not_found to get that value back instead of a NotFoundError; omit it entirely to get the exception. Any value works, including None.

filter(array, condition, if_empty=...)

Keep items where condition is true. condition is a predicate function or a boolean list the same length as array. Pass if_empty to get that value back instead of [] when nothing matches.

unique(array, keep="first")

Distinct items, order preserved. keep="last" keeps the last occurrence instead of the first.

sort(array, by=None, key=None, reverse=False)

Sort a flat list, or a 2D table by column by (a 1-based number or a column name). key overrides both with a custom function.

Loading data

Read a file straight into a table — standard library only, no pandas, polars or openpyxl:

from pylookup import read_table

read_table("sales.csv")                  # CSV, TSV, delimiter detected
read_table("sales.xlsx", sheet="Q1")     # .xlsx/.xlsm, dates become date objects
read_table("sales.json")                 # records, rows or columns

read_csv, read_excel, read_json and sheet_names are available individually. The old binary .xls format is not supported — save it as .xlsx or .csv first.

Example

table = [
    ["id", "name", "score"],
    [1, "alice", 90],
    [2, "bob", 75],
    [3, "carol", 60],
]

vlookup(2, table, 2)                     # "bob"
xlookup(3, [1, 2, 3], ["a", "b", "c"])   # "c"
sort(table[1:], by=3, reverse=True)      # highest score first (skip header row)

See src/examples/basic.py for more.

Publishing to PyPI

pip install build twine
python -m build
twine upload dist/*

Metadata

Release files for pylookups 0.1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pylookups 0.1.3
File Size Uploaded
pylookups-0.1.3.tar.gz 33.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pylookups 0.1.3
File Interpreter ABI Platform
pylookups-0.1.3-py3-none-any.whl Python 3 none any Details

Total release size: 49.3 kB

Release files / pylookups-0.1.3.tar.gz

Download URL pylookups-0.1.3.tar.gz
Size 33.2 kB
Tags Source
SHA-256 checksum
How to use checksums
c69db4df4b62f5b5689f3238c196e2a9c60d223941d372e001f8a9b7b5b4b1fc
BLAKE2b-256 checksum
How to use checksums
0c0b23cfb9bbf9c808121990a882791a8eb40f0035f88ee12f4c914c48c58a80
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Release files / pylookups-0.1.3-py3-none-any.whl

Download URL pylookups-0.1.3-py3-none-any.whl
Size 16.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8c6833afa6eacb4b8de93a4d399e4176b551c5b5099fc3761c1717e0eefb9f37
BLAKE2b-256 checksum
How to use checksums
7d25966dc8bc0f84b40d9a7945afdf833539725b11a09f3801ef9650a0b3489a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Release history Release notifications | RSS feed

This release

0.1.3 This release

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page