英文:
Nested partition data structure JavaScript
问题
我正在尝试找出适用于我的用例的最佳数据结构/类。
我有几个数组(都是长度为 n
),我想要使用它们创建一个分区。我希望能够至少嵌套分区一层(从示例中应该清楚)。我还希望能够使用类似 reduce
的函数来汇总一些其他数组的值(也都是长度为 n
),既在内部(嵌套)分区,又在外部(非嵌套)分区。
我在考虑一个类似这样的 API:
const arr1 = [1, 0, 0, 1, 1, 0, 0, 1];
const arr2 = ["A", "A", "A", "B", "C", "B", "B", "A"];
const arr3 = [100, 250, 100, 300, 150, 250, 300, 150];
const partition = Partition.from(arr2)
.nest(arr1)
.reduceWith({arr3}, (a, b) => a + b, 0);
partition.outer() // { "A": { arr3: 600 }, "B": { arr3: 850 }, "C": { arr3: 150 } }
partition.inner() // { "A0": { arr3: 350 }, "A1" : { arr3: 250 }, "B0": { arr3: 550 }, "B1": { arr3: 300 }, "C1": { arr3: 150 } }
// ^^我使用了类似 "A0","B1" 等字符串作为键,以使事情更清晰一些,
// 但在实际使用中,我可能会使用 JSON 字符串,例如 "{ "arr2":"B","arr1":0}",
// 以使分区 ID 不那么模糊不清。
重要的是,嵌套数组的具体值(但不是长度或唯一值)会随时间变化,因此数据结构需要允许反应性(我正在使用 Solid JS)。内部分区可能更经常更改,它们只应在必要时重新计算。
有人有任何想法或了解一个好的模式吗?
英文:
I'm trying to figure out what would be the best data structure/class for my use case.
I have several arrays (all of length n
) that I want to use to create a partition. I want to be able to nest the partition at least one layer deep (hopefully will be clear from the example). I also want to be able to summarize the values of some other arrays (also of length n
) with a reduce
-like function, both within the inner (nested) and the outer (non-nested) partitions.
I'm thinking an API like this:
const arr1 = [1, 0, 0, 1, 1, 0, 0, 1];
const arr2 = ["A", "A", "A", "B", "C", "B", "B", "A"];
const arr3 = [100, 250, 100, 300, 150, 250, 300, 150];
const partition = Partition.from(arr2)
.nest(arr1)
.reduceWith({arr3}, (a, b) => a + b, 0);
partition.outer() // { "A": { arr3: 600 }, "B": { arr3: 850 }, "C": { arr3: 150 } }
partition.inner() // { "A0": { arr3: 350 }, "A1" : { arr3: 250 }, "B0": { arr3: 550 }, "B1": { arr3: 300 }, "C1": { arr3: 150 } }
// ^^I used strings like "A0", "B1" etc..., as keys to make things a bit clearer,
// but in practice I might use JSON strings, e.g. "{"arr2":"B","arr1":0}",
// to make the partition ids less ambiguous
Importantly, the specific values (but not the length or unique values) of the nesting arrays will change over time, so the data structure needs to allow for reactivity (I am using Solid JS). The inner partition might change more often than the outer one, and they should only be recomputed when necessary.
Anyone has any ideas/knows of a good pattern?
答案1
得分: 1
以下是您要翻译的代码部分:
class Partition {
constructor() {
this.levels = [];
this.values = [];
}
addLevel(level) {
this.levels.push(level);
return this;
}
reduceWith(obj, reducer) {
[this.key, this.values] = Object.entries(obj)[0];
this.reducer = reducer;
return this;
}
produce(level=1) {
const levels = this.levels.slice(0, level);
const {key} = this;
return this.values.reduce((acc, value, i) => {
const group = levels.map(level => level[i]).join("");
if (group in acc) {
acc[group][key] = this.reducer(acc[group][key], value);
} else {
acc[group] = { [key]: value };
}
return acc;
}, {});
}
}
const arr1 = [1, 0, 0, 1, 1, 0, 0, 1];
const arr2 = ["A", "A", "A", "B", "C", "B", "B", "A"];
const arr3 = [100, 250, 100, 300, 150, 250, 300, 150];
const partition = new Partition()
.addLevel(arr2)
.addLevel(arr1)
.reduceWith({ arr3 }, (a, b) => a + b);
console.log(partition.produce(0)); // { "": { arr3: 1600 } }
console.log(partition.produce(1)); // { "A": { arr3: 600 }, "B": { arr3: 850 }, "C": { arr3: 150 } }
console.log(partition.produce(2)); // { "A0": { arr3: 350 }, "A1": { arr3: 250 }, "B0": { arr3: 550 }, "B1": { arr3: 300 }, "C1": { arr3: 150 } }
英文:
You could create a class Partition
(which must be instanciated with new
), and define a method addLevel
(corresponding to both from
and nest
in your suggestion) which returns the instance again for chaining, and a method reduceWith
which also returns the instance.
Then what you call outer
and inner
would be combined in a single method produce
that takes a level as argument (like 1 for outer, and 2 for inner). This is more generic, and you could even generate a grand total (without partitioning) by passing level 0 as argument.
Here it is:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
class Partition {
constructor() {
this.levels = [];
this.values = [];
}
addLevel(level) {
this.levels.push(level);
return this;
}
reduceWith(obj, reducer) {
[this.key, this.values] = Object.entries(obj)[0];
this.reducer = reducer;
return this;
}
produce(level=1) {
const levels = this.levels.slice(0, level);
const {key} = this;
return this.values.reduce((acc, value, i) => {
const group = levels.map(level => level[i]).join("");
if (group in acc) {
acc[group][key] = this.reducer(acc[group][key], value);
} else {
acc[group] = {[key]: value};
}
return acc;
}, {});
}
}
const arr1 = [1, 0, 0, 1, 1, 0, 0, 1];
const arr2 = ["A", "A", "A", "B", "C", "B", "B", "A"];
const arr3 = [100, 250, 100, 300, 150, 250, 300, 150];
const partition = new Partition()
.addLevel(arr2)
.addLevel(arr1)
.reduceWith({arr3}, (a, b) => a + b);
console.log(partition.produce(0)); // { "": { arr3: 1600 } }
console.log(partition.produce(1)); // { "A": { arr3: 600 }, "B": { arr3: 850 }, "C": { arr3: 150 } }
console.log(partition.produce(2)); // { "A0": { arr3: 350 }, "A1" : { arr3: 250 }, "B0": { arr3: 550 }, "B1": { arr3: 300 }, "C1": { arr3: 150 } }
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论