From 448f5a8bc51cfeb62a5f17f7f6dccdc48d57a698 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 2 May 2026 01:14:22 +0000 Subject: [PATCH 01/12] Iteration 299: hashArray + Series.items/iteritems + DataFrame.itertuples Run: https://github.com/githubnext/tsessebe/actions/runs/25239808128 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- playground/hash_array_itertuples.html | 132 ++++++++++++++++++++++++++ src/core/frame.ts | 40 ++++++++ src/core/series.ts | 28 ++++++ src/index.ts | 1 + src/stats/hash_array.ts | 106 +++++++++++++++++++++ src/stats/index.ts | 1 + tests/core/itertuples_items.test.ts | 59 ++++++++++++ tests/stats/hash_array.test.ts | 59 ++++++++++++ 8 files changed, 426 insertions(+) create mode 100644 playground/hash_array_itertuples.html create mode 100644 src/stats/hash_array.ts create mode 100644 tests/core/itertuples_items.test.ts create mode 100644 tests/stats/hash_array.test.ts diff --git a/playground/hash_array_itertuples.html b/playground/hash_array_itertuples.html new file mode 100644 index 00000000..4019b0ff --- /dev/null +++ b/playground/hash_array_itertuples.html @@ -0,0 +1,132 @@ + + + + + + tsb — hashArray / itertuples / Series.items Playground + + + +← Back to playground index +

hashArray / itertuples / Series.items

+

+ Utility hashing and row-iteration APIs — mirrors + pandas.util.hash_array, DataFrame.itertuples(), + and Series.items(). +

+ +
+

hashArray

+

Hash an array of scalar values element-wise (FNV-1a 64-bit).

+ + +
Click ▶ Run
+
+ +
+

Series.items() / iteritems()

+

Iterate over (label, value) pairs from a Series.

+ + +
Click ▶ Run
+
+ +
+

DataFrame.itertuples()

+

Iterate over rows as plain objects with an Index field.

+ + +
Click ▶ Run
+
+ + + + diff --git a/src/core/frame.ts b/src/core/frame.ts index ddb641a1..05a1738a 100644 --- a/src/core/frame.ts +++ b/src/core/frame.ts @@ -581,6 +581,46 @@ export class DataFrame { yield* this._columns.entries(); } + /** + * Iterate over DataFrame rows as objects with an `Index` property plus + * one property per column — mirrors `DataFrame.itertuples()`. + * + * Unlike pandas' named-tuples (which are positional), JavaScript does not + * have positional tuples with named fields, so each row is returned as a + * plain object `{ Index: label, col1: val, col2: val, ... }`. The `Index` + * key matches the pandas `itertuples(name="Pandas")` default. + * + * @param index - Whether to include the row index as the `Index` field. + * Default `true`. + * @param name - Unused (kept for API parity); TypeScript records have no + * class name. + * + * @example + * ```ts + * const df = new DataFrame({ a: [1, 2], b: ["x", "y"] }); + * for (const row of df.itertuples()) { + * console.log(row); // { Index: 0, a: 1, b: "x" } then { Index: 1, a: 2, b: "y" } + * } + * ``` + */ + *itertuples( + index = true, + _name?: string, + ): IterableIterator> { + const nRows = this.index.size; + const colNames = this.columns.values as readonly string[]; + for (let i = 0; i < nRows; i++) { + const row: Record = {}; + if (index) { + row["Index"] = this.index.at(i) as Scalar; + } + for (const name of colNames) { + row[name] = this.col(name).iat(i); + } + yield row; + } + } + /** Iterate over `(rowLabel, rowSeries)` pairs — mirrors `DataFrame.iterrows()`. */ *iterrows(): IterableIterator<[Label, Series]> { const nRows = this.index.size; diff --git a/src/core/series.ts b/src/core/series.ts index 2410e13c..fa043e88 100644 --- a/src/core/series.ts +++ b/src/core/series.ts @@ -1180,6 +1180,34 @@ export class Series { groupby(by: readonly Scalar[] | Series): SeriesGroupBy { return new SeriesGroupBy(this as Series, by); } + + // ─── items / iteritems ──────────────────────────────────────────────────── + + /** + * Lazily iterate over `(label, value)` pairs — mirrors `Series.items()`. + * + * @example + * ```ts + * const s = new Series({ data: [10, 20], index: ["a", "b"] }); + * for (const [label, value] of s.items()) { + * console.log(label, value); // "a" 10 then "b" 20 + * } + * ``` + */ + *items(): IterableIterator<[Label, T]> { + const n = this.index.size; + for (let i = 0; i < n; i++) { + yield [this.index.at(i) as Label, this.iat(i) as T]; + } + } + + /** + * Alias for `items()` — mirrors `Series.iteritems()` (deprecated in pandas + * 1.5 but still widely used). + */ + *iteritems(): IterableIterator<[Label, T]> { + yield* this.items(); + } } function isIndexLike(v: unknown): v is Index