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