英文:
How to transform simple JSON matrix (rows and columns) to a record for each "data cell", with headers applied to each cell?
问题
这个JSON矩阵是通过这个JS代码生成的,用于处理这个拉丁动词变位表(点击“conjugation”以展开表格在Wiktionary上查看):
[
["indicative", "indicative", "singular", "singular", "singular", "plural", "plural", "plural"],
["indicative", "indicative", "first", "second", "third", "first", "second", "third"],
["active", "present", {"la":"accēdō"}, {"la":"accēdis"}, {"la":"accēdit"}, {"la":"accēdimus"}, {"la":"accēditis"}, {"la":"accēdunt"}],
...
]
问题是如何将这些左边和顶部的“header”应用到数据单元格中,以及如何输出最终的数据单元格,每个“header”都是一个布尔属性,如果它具有该属性,则将布尔值设置为true。
例如,最左上角的数据单元格,在添加所有头部作为布尔属性后,将如下所示:
{
la: 'accēdō',
active: true,
present: true,
indicative: true,
singular: true,
first: true,
}
你可以采用嵌套的循环来遍历矩阵,然后根据矩阵的结构逐步构建数据对象。对于每个数据单元格,你可以将对应的头部属性设置为true。这需要一些编程技巧和逻辑来处理嵌套的头部和数据。
如果你需要更详细的代码实现或指导,请提出具体问题,我可以提供更多帮助。
英文:
This JSON matrix was generated via this JS code against this Latin verb conjugation table (click the "conjugation" bar to expand the table to see it on Wiktionary):
[
[ "indicative" , "indicative" , "singular" , "singular" , "singular" , "plural" , "plural" , "plural" ],
[ "indicative" , "indicative" , "first" , "second" , "third" , "first" , "second" , "third" ],
[ "active" , "present" , {"la":"accēdō"} , {"la":"accēdis"} , {"la":"accēdit"} , {"la":"accēdimus"} , {"la":"accēditis"} , {"la":"accēdunt"} ],
[ "active" , "imperfect" , {"la":"accēdēbam"} , {"la":"accēdēbās"} , {"la":"accēdēbat"} , {"la":"accēdēbāmus"} , {"la":"accēdēbātis"} , {"la":"accēdēbant"} ],
[ "active" , "future" , {"la":"accēdam"} , {"la":"accēdēs"} , {"la":"accēdet"} , {"la":"accēdēmus"} , {"la":"accēdētis"} , {"la":"accēdent"} ],
[ "active" , "perfect" , {"la":"accessī"} , {"la":"accessistī"} , {"la":"accessit"} , {"la":"accessimus"} , {"la":"accessistis"} , {"la":"accessēre"} ],
[ "active" , "pluperfect" , {"la":"accesseram"} , {"la":"accesserās"} , {"la":"accesserat"} , {"la":"accesserāmus"} , {"la":"accesserātis"} , {"la":"accesserant"} ],
[ "active" , "future perfect" , {"la":"accesserō"} , {"la":"accesseris"} , {"la":"accesserit"} , {"la":"accesserimus"} , {"la":"accesseritis"} , {"la":"accesserint"} ],
[ "subjunctive" , "subjunctive" , "singular" , "singular" , "singular" , "plural" , "plural" , "plural" ],
[ "subjunctive" , "subjunctive" , "first" , "second" , "third" , "first" , "second" , "third" ],
[ "active" , "present" , {"la":"accēdam"} , {"la":"accēdās"} , {"la":"accēdat"} , {"la":"accēdāmus"} , {"la":"accēdātis"} , {"la":"accēdant"} ],
[ "active" , "imperfect" , {"la":"accēderem"} , {"la":"accēderēs"} , {"la":"accēderet"} , {"la":"accēderēmus"} , {"la":"accēderētis"} , {"la":"accēderent"} ],
[ "active" , "perfect" , {"la":"accesserim"} , {"la":"accesserīs"} , {"la":"accesserit"} , {"la":"accesserīmus"} , {"la":"accesserītis"} , {"la":"accesserint"} ],
[ "active" , "pluperfect" , {"la":"accessissem"} , {"la":"accessissēs"} , {"la":"accessisset"} , {"la":"accessissēmus"} , {"la":"accessissētis"} , {"la":"accessissent"} ],
[ "imperative" , "imperative" , "singular" , "singular" , "singular" , "plural" , "plural" , "plural" ],
[ "imperative" , "imperative" , "first" , "second" , "third" , "first" , "second" , "third" ],
[ "active" , "present" , null , {"la":"accēde"} , null , null , {"la":"accēdite"} , null ],
[ "active" , "future" , null , {"la":"accēditō"} , {"la":"accēditō"} , null , {"la":"accēditōte"} , {"la":"accēduntō"} ],
[ "non-finite forms" , "non-finite forms" , "active" , "active" , "active" , "passive" , "passive" , "passive" ],
[ "non-finite forms" , "non-finite forms" , "present" , "perfect" , "future" , "present" , "perfect" , "future" ],
[ "infinitives" , "infinitives" , {"la":"accēdere"} , {"la":"accessisse"} , {"la":"accessūrum esse"} , null , null , null ],
[ "participles" , "participles" , {"la":"accēdēns"} , null , {"la":"accessūrus"} , null , null , null ],
[ "verbal nouns" , "verbal nouns" , "gerund" , "gerund" , "gerund" , "gerund" , "supine" , "supine" ],
[ "verbal nouns" , "verbal nouns" , "genitive" , "dative" , "accusative" , "ablative" , "accusative" , "ablative" ],
[ "verbal nouns" , "verbal nouns" , {"la":"accēdendī"} , {"la":"accēdendō"} , {"la":"accēdendum"} , {"la":"accēdendō"} , {"la":"accessum"} , {"la":"accessū"} ]
]
The JSON objects are cells with so-called "data", and the string cells area "header" cells. The null cells are just ignored.
Zoom out, and you'll see how the headers are somewhat creatively applied to the more right/bottom-directed cells.
- You can have multiple layers of headers above data cells.
- You can have multiple layers to the left of data cells.
- The "above" header cells get reset occasionally, which you can tell because there are no data cells in that row (it's all strings).
The question is, how do you apply the header cells to the data cells, and output the final data cells with properties for each header, in an array? That is, just make each header be a boolean property, and if it has that property, set the boolean on that data cell to true.
So for example, the top-left-most data cell, when all the headers are added as boolean properties to it, would look like this:
{
la: 'accēdō',
active: true,
present: true,
indicative: true,
singular: true,
first: true,
}
Toward the middle on the bottom, we might have this record in the final array too:
{
gerund: true,
dative: true,
la: 'accēdendō',
'verbal nouns': true,
}
How can you move across and down this matrix, to properly apply these left and top "headers" to the data cells? I have been at this for days and haven't figured it out, tinkering with the code in many ways, but just throwing my hands up and trying to just hack and mutate the DOM to strip what I need. But given that we got to the point of isolating the complicated HTML table as a JSON matrix, maybe it is a simpler more straightforward problem to try and write a quick algorithm to apply the headers in the matrix to the data cells in the matrix.
答案1
得分: 1
根据您提供的链接的函数,我进行了一些修改以使其适用于问题中呈现的矩阵。
要创建具有true
值的键,您可以使用Object.fromEntries
:
// 将矩阵转换为所需的扁平对象的函数。
function toObject(matrix) {
const result = [];
const tabQualifier = [];
const colQualifiers = [];
let data = true;
for (const [...row] of matrix) {
// 找到第一次找到数据的列索引 -
// 知道数据元素由对象表示
// 而修饰符由字符串数据类型表示
const dataAt = row.findIndex(content => typeof content === "object");
// 一些标题行在第一列中有一个TD元素(阿拉伯语表中的不一致性),
// 因此只有在非第一列时才将其视为数据
if (dataAt < 1) {
// 没有数据; 所以这是仅有修饰符的标题
// 如果修饰符在第一列中存在,它是表修饰符(最高级修饰符)
if (row[0]) tabQualifier[0] = row[0];
// 如果前一行有数据,我们进入新的部分...所以重置列修饰符
if (data) colQualifiers.length = 0;
row.forEach((col, i) => (colQualifiers[i] ??= []).push(col));
} else {
// 具有数据的行
// 对于没有列标题的部分,创建一个虚拟列修饰符
if (!colQualifiers.length) colQualifiers[dataAt] = [];
const qualifier = [...tabQualifier, ...row.splice(0, dataAt)];
// 对于每个具有数据的列,将其与修饰符连接起来
colQualifiers.slice(dataAt).forEach((colQualifier, i) => {
if (row[i]) {
result.push({
// 为每个相关修饰符创建带有true值的键
...Object.fromEntries(Array.from([...qualifier, ...colQualifier], qual => [qual, true])),
...row[i]
});
}
});
}
data = dataAt >= 1;
}
return result;
}
// 问题中呈现的矩阵
const matrix = [[ "indicative" , "indicative" , "singular" , "singular" , "singular" , "plural" , "plural" , "plural" ],[ "indicative" , "indicative" , "first" , "second" , "third" , "first" , "second" , "third" ],[ "active" , "present" , {"la":"accēdō"} , {"la":"accēdis"} , {"la":"accēdit"} , {"la":"accēdimus"} , {"la":"accēditis"} , {"la":"accēdunt"} ],[ "active" , "imperfect" , {"la":"accēdēbam"} , {"la":"accēdēbās"} , {"la":"accēdēbat"} , {"la":"accēdēbāmus"} , {"la":"accēdēbātis"} , {"la":"accēdēbant"} ],[ "active" , "future" , {"la":"accēdam"} , {"la":"accēdēs"} , {"la":"accēdet"} , {"la":"accēdēmus"} , {"la":"accēdētis"} , {"la":"accēdent"} ],[ "active" , "perfect" , {"la":"accessī"} , {"la":"accessistī"} , {"la":"accessit"} , {"la":"accessimus"} , {"la":"accessistis"} , {"la":"accessēre"} ],[ "active" , "pluperfect" , {"la":"accesseram"} , {"la":"accesserās"} , {"la":"accesserat"} , {"la":"accesserāmus"} , {"la":"accesserātis"} , {"la":"accesserant"} ],[ "active" , "future perfect" , {"la":"accesserō"} , {"la":"accesseris"} , {"la":"accesserit"} , {"la":"accesserimus"} , {"la":"accesseritis"} , {"la":"accesserint"} ],[ "subjunctive" , "subjunctive" , "singular" , "singular" , "singular" , "plural" , "plural" , "plural" ],[ "subjunctive" , "subjunctive" , "first" , "second" , "third" , "first" , "second" , "third" ],[ "active" , "present" , {"la":"accēdam"} , {"la":"accēdās"} , {"la":"accēdat"} , {"la":"accēdāmus"} , {"la":"accēdātis"} , {"la":"accēdant"} ],[ "active" , "imperfect" , {"la":"accēderem"} , {"la":"accēderēs"} , {"la":"accēderet"} , {"la":"accēderēmus"} , {"la":"accēderētis"} , {"la":"accēderent"} ],[ "active" , "perfect" , {"la":"accesserim"} , {"la":"accesserīs"} , {"la":"accesserit"} , {"la":"accesserīmus"} , {"la":"accesserītis"} , {"la":"accesserint"} ],[ "active" , "pluperfect" , {"la":"accessissem"} , {"la":"accessissēs"} , {"la":"accessisset"} , {"la":"accessissēmus"} , {"la":"accessissētis"} , {"la":"accessissent"} ],[ "imperative" , "imperative" , "singular" , "singular" , "singular" , "plural" , "plural" , "plural" ],[ "imperative" , "imperative" , "first" , "second" , "third" , "first" , "second" , "third" ],[ "active" , "present" , null , {"la":"accēde"} , null , null , {"la":"accēdite"} , null ],
[ "active" , "future" , null , {"la":"accēditō"} , {"la":"accēditō"} , null , {"la":"accēditōte"} , {"la":"accēduntō"} ],[ "non-finite forms"
<details>
<summary>英文:</summary>
Taking the function you linked to, I made a few modifications to make it work for the matrix presented in the question.
To create keys with `true` as values, you could use `Object.fromEntries`:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
// Function to convert matrix to the desired flat object.
function toObject(matrix) {
const result = [];
const tabQualifier = [];
const colQualifiers = [];
let data = true;
for (const [...row] of matrix) {
// Find the column index where first data is found --
// knowing that a data element is represented by an object
// while a qualifier is represented by a string data type
const dataAt = row.findIndex(content => typeof content === "object");
// Some heading rows have a TD element in first column (an inconsistency in the table for Arabic),
// so only consider it data when in a non-first column
if (dataAt < 1) { // No data; so this is a heading with only qualifier(s)
// If the qualifier is present in the first column, it's a table qualifier (highest-level qualifier)
if (row[0]) tabQualifier[0] = row[0];
// If the previous row had data, we enter a new section... so reset the column-qualifiers
if (data) colQualifiers.length = 0;
row.forEach((col, i) => (colQualifiers[i] ??= []).push(col));
} else { // Row with data
// For sections that have no column headers, create one dummy column qualifier
if (!colQualifiers.length) colQualifiers[dataAt] = [];
const qualifier = [...tabQualifier, ...row.splice(0, dataAt)];
// For each column with data, join it with the qualifiers
colQualifiers.slice(dataAt).forEach((colQualifier, i) => {
if (row[i]) {
result.push({
// Create keys with true as value for each of the relevant qualifiers
...Object.fromEntries(Array.from([...qualifier, ...colQualifier], qual => [qual, true])),
...row[i]
});
}
});
}
data = dataAt >= 1;
}
return result;
}
// The matrix as presented in the question
const matrix = [[ "indicative" , "indicative" , "singular" , "singular" , "singular" , "plural" , "plural" , "plural" ],[ "indicative" , "indicative" , "first" , "second" , "third" , "first" , "second" , "third" ],[ "active" , "present" , {"la":"accēdō"} , {"la":"accēdis"} , {"la":"accēdit"} , {"la":"accēdimus"} , {"la":"accēditis"} , {"la":"accēdunt"} ],[ "active" , "imperfect" , {"la":"accēdēbam"} , {"la":"accēdēbās"} , {"la":"accēdēbat"} , {"la":"accēdēbāmus"} , {"la":"accēdēbātis"} , {"la":"accēdēbant"} ],[ "active" , "future" , {"la":"accēdam"} , {"la":"accēdēs"} , {"la":"accēdet"} , {"la":"accēdēmus"} , {"la":"accēdētis"} , {"la":"accēdent"} ],[ "active" , "perfect" , {"la":"accessī"} , {"la":"accessistī"} , {"la":"accessit"} , {"la":"accessimus"} , {"la":"accessistis"} , {"la":"accessēre"} ],[ "active" , "pluperfect" , {"la":"accesseram"} , {"la":"accesserās"} , {"la":"accesserat"} , {"la":"accesserāmus"} , {"la":"accesserātis"} , {"la":"accesserant"} ],[ "active" , "future perfect" , {"la":"accesserō"} , {"la":"accesseris"} , {"la":"accesserit"} , {"la":"accesserimus"} , {"la":"accesseritis"} , {"la":"accesserint"} ],[ "subjunctive" , "subjunctive" , "singular" , "singular" , "singular" , "plural" , "plural" , "plural" ],[ "subjunctive" , "subjunctive" , "first" , "second" , "third" , "first" , "second" , "third" ],[ "active" , "present" , {"la":"accēdam"} , {"la":"accēdās"} , {"la":"accēdat"} , {"la":"accēdāmus"} , {"la":"accēdātis"} , {"la":"accēdant"} ],[ "active" , "imperfect" , {"la":"accēderem"} , {"la":"accēderēs"} , {"la":"accēderet"} , {"la":"accēderēmus"} , {"la":"accēderētis"} , {"la":"accēderent"} ],[ "active" , "perfect" , {"la":"accesserim"} , {"la":"accesserīs"} , {"la":"accesserit"} , {"la":"accesserīmus"} , {"la":"accesserītis"} , {"la":"accesserint"} ],[ "active" , "pluperfect" , {"la":"accessissem"} , {"la":"accessissēs"} , {"la":"accessisset"} , {"la":"accessissēmus"} , {"la":"accessissētis"} , {"la":"accessissent"} ],[ "imperative" , "imperative" , "singular" , "singular" , "singular" , "plural" , "plural" , "plural" ],[ "imperative" , "imperative" , "first" , "second" , "third" , "first" , "second" , "third" ],[ "active" , "present" , null , {"la":"accēde"} , null , null , {"la":"accēdite"} , null ],
[ "active" , "future" , null , {"la":"accēditō"} , {"la":"accēditō"} , null , {"la":"accēditōte"} , {"la":"accēduntō"} ],[ "non-finite forms" , "non-finite forms" , "active" , "active" , "active" , "passive" , "passive" , "passive" ],[ "non-finite forms" , "non-finite forms" , "present" , "perfect" , "future" , "present" , "perfect" , "future" ],[ "infinitives" , "infinitives" , {"la":"accēdere"} , {"la":"accessisse"} , {"la":"accessūrum esse"} , null , null , null ],[ "participles" , "participles" , {"la":"accēdēns"} , null , {"la":"accessūrus"} , null , null , null ],[ "verbal nouns" , "verbal nouns" , "gerund" , "gerund" , "gerund" , "gerund" , "supine" , "supine" ],[ "verbal nouns" , "verbal nouns" , "genitive" , "dative" , "accusative" , "ablative" , "accusative" , "ablative" ],[ "verbal nouns" , "verbal nouns" , {"la":"accēdendī"} , {"la":"accēdendō"} , {"la":"accēdendum"} , {"la":"accēdendō"} , {"la":"accessum"} , {"la":"accessū"} ]]
const obj = toObject(matrix);
console.log(obj);
<!-- end snippet -->
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论