You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by we...@apache.org on 2018/07/16 23:29:00 UTC
[arrow] branch master updated: ARROW-2771: [JS] Add row proxy
object accessor
This is an automated email from the ASF dual-hosted git repository.
wesm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/master by this push:
new ebc8dab ARROW-2771: [JS] Add row proxy object accessor
ebc8dab is described below
commit ebc8dabec52fa03c4424e56edf9a236417b26d84
Author: Brian Hulette <hu...@gmail.com>
AuthorDate: Mon Jul 16 19:28:54 2018 -0400
ARROW-2771: [JS] Add row proxy object accessor
Creates a custom `RowProxy` class based on the schema whenever a new `Table` is constructed, and yields instances of it in `get` and the iterator.
Now you could use the following code to compute the mean of the `score` column for all rows where `name === target`.
``` javascript
let sum = 0, count = 0;
for (let row of table) {
if (row.name === target) {
sum += row.score;
count += 1;
}
}
return sum/count;
```
Author: Brian Hulette <hu...@gmail.com>
Closes #2197 from TheNeuralBit/row-proxy and squashes the following commits:
a1be00fb <Brian Hulette> Move row proxy to StructView
2aa90779 <Brian Hulette> Store RowProxy constructor rather than re-writing a method
57af6433 <Brian Hulette> Table.get and Table iterator now return row proxy objects
---
js/src/ipc/writer/binary.ts | 2 +-
js/src/table.ts | 1 +
js/src/util/node.ts | 8 ++++----
js/src/vector/nested.ts | 29 ++++++++++++++++++++++++++++-
js/test/unit/table-tests.ts | 15 +++++++++++----
5 files changed, 45 insertions(+), 10 deletions(-)
diff --git a/js/src/ipc/writer/binary.ts b/js/src/ipc/writer/binary.ts
index 166d4b8..2bab428 100644
--- a/js/src/ipc/writer/binary.ts
+++ b/js/src/ipc/writer/binary.ts
@@ -82,7 +82,7 @@ export function* serializeFile(table: Table) {
// Then yield the footer metadata (not aligned)
({ metadataLength, buffer } = serializeFooter(new Footer(dictionaryBatches, recordBatches, table.schema)));
yield buffer;
-
+
// Last, yield the footer length + terminating magic arrow string (aligned)
buffer = new Uint8Array(magicAndPadding);
new DataView(buffer.buffer).setInt32(0, metadataLength, platformIsLittleEndian);
diff --git a/js/src/table.ts b/js/src/table.ts
index 8144c98..e3be9bb 100644
--- a/js/src/table.ts
+++ b/js/src/table.ts
@@ -111,6 +111,7 @@ export class Table implements DataFrame {
this.length = this.batchesUnion.length;
this.numCols = this.batchesUnion.numCols;
}
+
public get(index: number): Struct['TValue'] {
return this.batchesUnion.get(index)!;
}
diff --git a/js/src/util/node.ts b/js/src/util/node.ts
index e588cb7..8e58f6b 100644
--- a/js/src/util/node.ts
+++ b/js/src/util/node.ts
@@ -21,10 +21,10 @@ export class PipeIterator<T> implements IterableIterator<T> {
let write = (err?: any) => {
stream['removeListener']('error', write);
stream['removeListener']('drain', write);
- if (err) return this.throw(err);
+ if (err) { return this.throw(err); }
if (stream['writable']) {
do {
- if ((res = this.next()).done) break;
+ if ((res = this.next()).done) { break; }
} while (emit(stream, encoding, res.value));
}
return wait(stream, res && res.done, write);
@@ -56,10 +56,10 @@ export class AsyncPipeIterator<T> implements AsyncIterableIterator<T> {
let write = async (err?: any) => {
stream['removeListener']('error', write);
stream['removeListener']('drain', write);
- if (err) return this.throw(err);
+ if (err) { return this.throw(err); }
if (stream['writable']) {
do {
- if ((res = await this.next()).done) break;
+ if ((res = await this.next()).done) { break; }
} while (emit(stream, encoding, res.value));
}
return wait(stream, res && res.done, write);
diff --git a/js/src/vector/nested.ts b/js/src/vector/nested.ts
index fe9f7e9..6d1bd4a 100644
--- a/js/src/vector/nested.ts
+++ b/js/src/vector/nested.ts
@@ -128,9 +128,36 @@ export class DenseUnionView extends UnionView<DenseUnion> {
}
}
+type RowProxy = {[name: string]: any};
+interface RowViewConstructor<T extends RowProxy = RowProxy> {
+ readonly prototype: T & RowView;
+ new (data: Data<SparseUnion> & NestedView<any>, children?: Vector<any>[], rowIndex?: number): T & RowView;
+}
+
export class StructView extends NestedView<Struct> {
+ private RowView: RowViewConstructor;
+
+ constructor(data: Data<Struct>, children?: Vector<any>[]) {
+ super(data, children);
+
+ // Make a customized RowView that includes proxies for
+ class RowProxy extends RowView {}
+
+ const proto = RowProxy.prototype;
+
+ data.type.children.forEach(function (f, i) {
+ Object.defineProperty(proto, f.name, {
+ get: function () {
+ return (this as any as RowView).get(i);
+ },
+ enumerable: true
+ });
+ });
+
+ this.RowView = (RowProxy as any);
+ }
protected getNested(self: StructView, index: number) {
- return new RowView(self as any, self._children, index);
+ return new self.RowView(self as any, self._children, index);
}
protected setNested(self: StructView, index: number, value: any): void {
let idx = -1, len = self.numChildren, child: Vector | null;
diff --git a/js/test/unit/table-tests.ts b/js/test/unit/table-tests.ts
index 32b15fa..39b27f9 100644
--- a/js/test/unit/table-tests.ts
+++ b/js/test/unit/table-tests.ts
@@ -86,13 +86,20 @@ describe(`Table`, () => {
});
test(`gets expected values`, () => {
for (let i = -1; ++i < values.length;) {
- expect(table.get(i).toArray()).toEqual(values[i]);
+ const row = table.get(i);
+ const expected = values[i];
+ expect(row.f32).toEqual(expected[F32]);
+ expect(row.i32).toEqual(expected[I32]);
+ expect(row.dictionary).toEqual(expected[DICT]);
}
});
test(`iterates expected values`, () => {
let i = 0;
for (let row of table) {
- expect(row.toArray()).toEqual(values[i++]);
+ const expected = values[i++];
+ expect(row.f32).toEqual(expected[F32]);
+ expect(row.i32).toEqual(expected[I32]);
+ expect(row.dictionary).toEqual(expected[DICT]);
}
});
describe(`scan()`, () => {
@@ -252,8 +259,8 @@ describe(`Table`, () => {
let idx = 0, expected_row;
for (let row of selected) {
expected_row = values[idx++];
- expect(row.get(0)).toEqual(expected_row[F32]);
- expect(row.get(1)).toEqual(expected_row[DICT]);
+ expect(row.f32).toEqual(expected_row[F32]);
+ expect(row.dictionary).toEqual(expected_row[DICT]);
}
});
test(`table.toString()`, () => {