我有一个目录数组,其中catId
可以重复。
每个目录都有唯一的segmentId
const catalogs = [
{ catID: 3, segmentId: '3', segmentName: 'S3' },
{ catID: 2, segmentId: '2', segmentName: 'S2' },
{ catID: 2, segmentId: '3', segmentName: 'S3' },
{ catID: 1, segmentId: '1', segmentName: 'S1' },
{ catID: 1, segmentId: '2', segmentName: 'S2' },
{ catID: 1, segmentId: '3', segmentName: 'S3' }
];
意味着每个catId
可能有多个segmentId,但该特定catId
的segmentId不能重复
现在,我要将线段数组指定给主目录数组:
例如,下面是我需要分配的段数组示例:
[{id: '3', name: 'S3'},{id: '4', name: 'S4'},{id: '5', name: 'S5'}]
我期待这样的回应:
[
{ catID: 3, segmentId: '3', label: { segmentIDName: '3_S3' } },
{ catID: 3, segmentId: '4', label: { segmentIDName: '4_S4' } },
{ catID: 3, segmentId: '5', label: { segmentIDName: '5_S5' } },
{ catID: 2, segmentId: '2', label: { segmentIDName: '2_S2' } },
{ catID: 2, segmentId: '3', label: { segmentIDName: '3_S3' } },
{ catID: 2, segmentId: '4', label: { segmentIDName: '4_S4' } },
{ catID: 2, segmentId: '5', label: { segmentIDName: '5_S5' } },
{ catID: 1, segmentId: '1', label: { segmentIDName: '1_S1' } },
{ catID: 1, segmentId: '2', label: { segmentIDName: '2_S2' } },
{ catID: 1, segmentId: '3', label: { segmentIDName: '3_S3' } },
{ catID: 1, segmentId: '4', label: { segmentIDName: '4_S4' } },
{ catID: 1, segmentId: '5', label: { segmentIDName: '5_S5' } }
]
我自己也尝试过解决这个问题,我已经很接近了,但没有得到预期的结果:
const catalogs = [
{ catID: 2, segmentId: '2', segmentName: 'S2' },
{ catID: 1, segmentId: '1', segmentName: 'S1' },
{ catID: 1, segmentId: '2', segmentName: 'S2' }
];
function addSegmentsToCatalogs(segments){
let catalogUid = catalogs[0].catID;
const lastCatalog = catalogs.slice(-1).pop();
const insertionArray = [];
catalogs.forEach(async (catalog) => {
if (catalogUid != catalog.catID) {
segments.forEach((segment) => {
insertionArray.push({
catalogId: catalogUid,
segmentId: segment.id,
segmentName: segment.name,
});
});
catalogUid = catalog.catID;
}
if (!segments.some((segment) => segment.id === catalog.segmentId)) {
segments.push({ id: catalog.segmentId, name: catalog.segmentName });
if (
catalog.catID == lastCatalog.catID &&
catalog.segmentId == lastCatalog.segmentId
) {
segments.forEach((segment) => {
insertionArray.push({
catalogId: catalogUid,
segmentId: segment.id,
segmentName: segment.name,
});
});
}
}
});
console.log(insertionArray);
return insertionArray;
}
addSegmentsToCatalogs([{id: '3', name: 'S3'}])
任何人都可以帮助我找到这个问题或建议我更好的方法来解决这个问题吗?
7条答案
按热度按时间5jvtdoz21#
根据我的理解,您正在尝试基于传递的
segments
数组创建对象/将对象推送到catalogs
数组中,并且segmentID
对于每个catID
都是唯一的。如果是,以下是实现此要求的步骤**:**Array#map
在catalogs
数组上进行迭代,将segementId
连接到segmentName
中,并返回catID
,即catIDArr
Set
方法从catIDArr
获取唯一catId,即uniqueCatIDs
segments
数组和uniqueCatIDs
数组,将新对象压入catalogs
数组。现场演示**:**
kzmpq1sx2#
一些想法:
通过在不改变给定数据的情况下具有需要分组的元素的数据结构和需要笛卡尔积的另一数据集,可以通过具有其优点和缺点的至少两种方法来解决该任务:
拿一些Map
首先,您可以使用嵌套的
Map
并按catID
和segmentId
分组。外部的
map
如下所示:然后,在保持给定数据集的情况下,迭代外部Map的密钥和
segements
,得到笛卡尔积。最后将所有内部Map的值作为平面数组。
优点:
缺点:
x一个一个一个一个x一个一个二个x
拿一个物体
这种方法遵循在迭代进行的同时更新直接结果的思想。
优点:
缺点:
catID
/segmentId
的可见组、catID
的数组(类型保存)和结果。catID
的顺序。一个三个三个一个
envsm3lx3#
个人陈述
编辑/备注-由于OP更改了最终数据格式的要求,因此在最初提供的解决方案中添加了一个小的代码重构。
2022-12-09
**下面提供的解决方案实现了一种使用预处理的查找数据的方法...
catIDs
setcatSegments
对象用于目录ID和段ID的现有组合。中间结果是新创建的有效目录项的数组,然后通过经由
flatMap
在现有catID
的数组上迭代来计算,其中对于每个catID
,试图通过对所传递的segments
数组进行reduce
运算来创建新目录项的数组。通过查找每个可能的目录项是否已作为相同catID
和segmentId
值的组合存在,可以确保该目录项的有效性。2022-12-11
进行了其他更改**修改后的示例代码保持上述原始实现不变,但引入了附加的
map
ping任务,该任务根据OP的数据结构变化为先前结果数组的每个目录项创建新项,因此Map函数接受OP的基本形式的目录项并创建新的标记目录项。这也证明了所提供的第一方法的鲁棒性。
一个二个一个一个
rt4zxlrg4#
我的previous answer是基于问题的前一个版本,而问题的当前版本似乎有了很大的变化(或者我只是误读了它)。无论如何,这似乎做了所需的事情,相当简单:
我认为将最后一行注解掉会更符合逻辑,在这种情况下,它给出的输出更像这样,没有
label
字段及其合并的数据属性:在这两种情况下,逻辑都与这里的许多其他逻辑类似,首先使用一个非常标准的实用函数
groupBy
将catalogs
转换为:然后使用
Object .entries
将其转换为键值对数组,其中键类似于_3
,值是{catID, segmentId, segmentName}
对象数组(添加前导下划线是为了避免在迭代Object时对键进行数字排序,最后将其删除)。然后使用
.map
,我们将它们转换为更简单的格式:对于
newSegs .reduce
,我们将新段添加到每个段中,得到以下结果:通过
.flatMap
调用,我们对属性进行了再水合,使结构扁平化,并顺便删除了用于排序的_
,从而得到了上面的首选结构。最后,我们使用
{label}
子对象将结果.map
到新对象中。如果这确实是您想要的格式,那么我建议将
.flatmap
和.map
调用替换为:它也会做同样的事情。
nue99wik5#
db2dz4w86#
在得到答案之前:输入数据表明输入段名称字符串的模式是大写字母
S
后跟整数序列。number
类型最好表示数据集输出数组中每个对象的segmentId
值...number
可以使用内置方法进行字符串化,成功率为100%-这意味着,如果以后需要字符串形式的值,可以根据需要轻松地执行此操作,但反之则不成立:大多数字符串不能被解析为数字。在上面的上下文中,您可以使用转换函数将每个输入项解析为所需的输出结构(并在此过程中验证值)。请参见下面的示例代码:
TSPlayground
从TS Playground编译的JS:
根据您的意见更新:如果您的实际数据集不同(例如,段名称不完全符合您在问题中显示的格式),以致上述观察结果不适用,那么-当然-您不必将段标识符解析为数字:
TSPlayground的完整代码
从TS Playground编译的JS:
hlswsv357#
我们可以通过添加一个
groupBy
实用函数来相当简单地完成这一任务,这在许多库中都可以找到。我们首先使用
groupBy
基于共享的catID
将输入分成多个组,得到如下结果:在上面调用
Object .entries
会得到这样的结果:现在,我们通过调用
flatMap
,传递一个Map到新片段的函数,创建与主记录匹配的对象,来转换每个片段并将结果扁平化。将它们附加到记录中并返回整个集合。唯一有点奇怪的是,我们必须通过将catID
Package 在Number
中来转换catID
。我们需要这样做是因为当我们在groupBy
中创建一个带有数字键的对象时,它们会在幕后被转换成字符串,我们可以使用Map
来代替,这样就避免了这个问题,但是会增加一些稍微复杂的语法。我们可以很容易地将
groupBy
函数内联到主函数中,但这是一个可广泛重用的函数;如果您还没有使用Ramda、lodash或Underscore之类的工具,我建议您在实用程序库中保存一些这样的工具。