JavaScript:如何映射两个对象以获得将第一个对象的 ID 映射到另一个对象的名称的输出?
Posted
技术标签:
【中文标题】JavaScript:如何映射两个对象以获得将第一个对象的 ID 映射到另一个对象的名称的输出?【英文标题】:JavaScript: How to map two objects to get the output which map the Id of first object to the name of other object? 【发布时间】:2021-08-07 03:26:06 【问题描述】:我正在尝试制作一个将 data2 对象值映射到 data1 名称的函数。
我试图用 data1 迭代 data2 object2 但它不能正常工作。我可以映射它们,但当 data2 中不存在 data1 时,我无法获取它的值。
有什么方法可以正确映射以获得代码中提到的所需输出?
let data1 =
attributes: [
Id: 'test1',
Name: 'Test1',
Type: 'date'
,
Id: 'test2',
Name: 'Test2',
Type: 'string'
,
Id: 'test3',
Name: 'Test3',
Type: 'string'
,
Id: 'test4',
Name: 'Test4',
Type: 'boolean'
]
;
let data2 =
value: [
test1: '10-12-2021',
test2: '4',
dummy: 'ignore me'
,
test3: '3',
test4: true,
abc: 'ignore me'
,
test1: '12-12-2023',
test3: '42',
dummy1: 'ignore me'
]
;
//output
let ouput =
rows: [
Test1: '10/12/2021',
Test2: '4',
Test3: '',
Test4: ''
,
Test1: '',
Test2: '',
Test3: '3',
Test4: 'Y'
,
Test1: '12/12/2023',
Test2: '',
Test3: '42',
Test4: ''
]
;
//function
function mapper(data1, data2)
let formattedValue = [];
data2.value.forEach(val =>
let data = ;
for (let prop in val)
let name;
const filter = data1.attributes.filter(el => el.Id === prop)[0];
if (filter)
name = filter.Name;
switch (filter.Type)
case 'boolean':
data[name] =
val[prop] === true ? 'Y' : val[prop] === false ? 'N' : '';
break;
case 'date':
data[name] = new Date(val[prop]).toLocaleDateString();
break;
default:
data[name] = val[prop];
break;
formattedValue.push(data);
);
return formattedValue;
console.log(mapper(data1, data2));
如果我将 data2 作为空值传递,我希望得到低于输出的值
let data1 =
attributes: [
Id: 'test1',
Name: 'Test1',
Type: 'string'
,
Id: 'test2',
Name: 'Test2',
Type: 'string'
,
Id: 'test3',
Name: 'Test3',
Type: 'string'
,
Id: 'test4',
Name: 'Test4',
Type: 'boolean'
]
;
let data2 =
value: [
]
;
//output
let ouput =
rows: [
Test1: '',
Test2: '',
Test3: '',
Test4: ''
,
]
;
【问题讨论】:
【参考方案1】:const data1 = attributes:[Id:'test1',Name:'Test1',Type:'date',Id:'test2',Name:'Test2',Type:'string',Id:'test3',Name:'Test3',Type:'string',Id:'test4',Name:'Test4',Type:'boolean']
data2 = value:[test1:'10-12-2021',test2:'4',test3:'3',test4:true,test1:'12-12-2023',test3:'42'];
data3 = value: []
const mapper = (x, y) =>
const row = x.attributes.map(e => [e.Id, e.Name])
format = e => switch (true)
case typeof e === 'boolean':
return e ? 'Y' : 'N'
case isNaN(e) && !isNaN(Date.parse(e)):
return new Date(e).toLocaleDateString()
default: return e
const rows = (y.value.length ? y.value : [1]).map(e =>
Object.fromEntries(row.map(([k, v]) => [v, format(e[k]) ?? '']))
)
return rows
console.log(mapper(data1, data2))
console.log(mapper(data1, data3))
.as-console-wrapper max-height: 100% !important; top: 0;
说明:
y.value.length ? y.value : [1]
检查data.value
是否为空,如果不是则返回data.value
。如果是,则返回 array
和 1 个元素(可以是任何值,只需进行 1 次迭代即可满足您对空数据的要求,因此值在这里并不重要。
其余代码应该很清楚,如果没有,请告诉我。
【讨论】:
非常感谢。如果我需要为 data1 属性添加更多类型支持怎么办?我们如何支持日期或整数等多种类型? 例如我想将当前日期格式转换为 mm/dd/yyyy @Bravo 现在是否符合您的要求?如果不是,为什么?【参考方案2】:更新
因为即使data2.values
为空,您也需要最少的一组值。如果我们在数组为空时添加空对象,我已经给出的解决方案将起作用,因此在下面添加将解决它。
// I had to add below lines to get your desired result
// if `data2.value` is empty array
const arrayToLoop = [...data2.value];
if(arrayToLoop.length === 0)
arrayToLoop.push();
现在我们将循环变量arrayToLoop
而不是data2.value
还写了一个小函数,用于根据给定类型转换值,您可以根据自己的需要扩展它
function parseValue(type, value)
if(value.length==0)
return '';
switch(type.toLowerCase())
case 'boolean':
return value === true ? 'Y' : value === false ? 'N' : '';
case 'date':
return new Date(value).toLocaleDateString();
default:
return value;
首先,我将获取所有键和标签映射,并查看每个键的所有值。 请注意我在下面是如何完成的。
如果您遇到任何问题,请告诉我。
function parseValue(type, value)
if(value.length==0)
return '';
switch(type.toLowerCase())
case 'boolean':
return value === true ? 'Y' : value === false ? 'N' : '';
case 'date':
return new Date(value).toLocaleDateString();
default:
return value;
function BusinessObjectMapper(data1, data2)
const arrayToLoop = [...data2.value];
if(arrayToLoop.length === 0)
arrayToLoop.push();
const rows = arrayToLoop.map(v=>
let r = ;
data1.attributes.forEach(o=>
let Id, Name, Type = o;
r[Name]=parseValue(Type, v[Id]||'');
)
return r;
)
return
rows
;
let data1 =
attributes: [
Id: 'test1',
Name: 'Test1',
Type:'string'
,
Id: 'test2',
Name: 'Test2',
Type:'boolean',
,
Id: 'test3',
Name: 'Test3',
Type:'date'
,
Id: 'test4',
Name: 'Test4',
Type:'un-known',
]
;
let data2 =
value: [
test1: '1',
test2: true
,
test3: '02/02/2020',
test4: '42'
,
test1: 'deepak',
test3: '01/01/2021'
]
;
let data2_empty =
value: []
console.log(BusinessObjectMapper(data1, data2));
console.log(BusinessObjectMapper(data1, data2_empty));
【讨论】:
谢谢,迪帕克。当 data2 有空值时失败。让 data1 = attributes: [ Id: 'test1', Name: 'Test1' , Id: 'test2', Name: 'Test2' , Id: 'test3' ,名称:'Test3' , ID:'test4',名称:'Test4'] ;让 data2 = 值:[ ] ; //输出 let 输出 = rows: [ Test1: '', Test2: '', Test3: '', Test4: '' , ] ; 我还修改了问题以支持类型 实际上你的 data2 不正确它不是正确的对象它应该是 value: [ ] ;
注意value
是一个可以清空对象的array
所以
而不是单个
希望它现在清楚?
我的错。 data2 将是 value:[ ] 我稍微修改了问题以支持不同的类型。是否可以更新解决方案?
不要让它变得敏捷请:P,当有完整代码时,您至少可以应用 switch case,打开 50 的赏金看起来像您正在参加我们的考试并想要准确的结果,那么只会给 50 分.社区是为了帮助你解决你的问题。没有完全完成你的任务。【参考方案3】:
我通过使用扩展运算符和 Array.prototype.reduce() 解决了对象类型问题。
const data1 =
attributes: [
Id: "test1",
Name: "Test1",
Type: "date",
,
Id: "test2",
Name: "Test2",
Type: "string",
,
Id: "test3",
Name: "Test3",
Type: "string",
,
Id: "test4",
Name: "Test4",
Type: "boolean",
,
],
;
const data2 =
value: [
test1: "10-12-2021",
test2: "4",
,
test3: "3",
test4: true,
,
test1: "12-12-2023",
test3: "42",
,
],
;
//function
const data11 =
attributes: [
Id: "test1",
Name: "Test1",
Type: "string",
,
Id: "test2",
Name: "Test2",
Type: "string",
,
Id: "test3",
Name: "Test3",
Type: "string",
,
Id: "test4",
Name: "Test4",
Type: "boolean",
,
],
;
const data12 =
value: [],
;
function mapper(data1, data2)
const columns = data1.attributes.reduce((prev, item) =>
prev[item["Id"]] = item;
return prev;
, );
const emptyValues = Object.keys(columns).reduce((prev, item) =>
prev[columns[item].Name] = "";
return prev;
, );
const getValueByType = (key, v) =>
switch (columns[key].Type)
case "boolean":
return v ? "Y" : "N";
case "date":
return new Date(v).toLocaleDateString();
default:
return v;
;
return
rows:
(data2.value &&
(data2.value.length == 0
? [emptyValues]
: data2.value.map((row) =>
Object.entries(row).reduce(
(rlt, [key, v]) =>
rlt[columns[key].Name] = getValueByType(key, v);
return rlt;
,
...emptyValues
)
))) ||
[],
;
const result1 = mapper(data1, data2);
console.log(result1.rows);
const result2 = mapper(data11, data12);
console.log(result2);
【讨论】:
它没有检查类型(布尔值,日期) 为什么需要验证?我们使用原始数据值而不是空字符串 '' 如果您在预期输出中看到我正在更改日期和布尔数据 输出中出现的是“Id”而不是“Name”,例如,根据输出,它应该是“Test1”而不是 test1 @Bravo 我使用名称而不是 id【参考方案4】:@ulou 的回答很棒!可以使用 reduce 来完成。我稍微更新了一个来源。
const mapper = (arr1, arr2) =>
const keys = arr1.attributes.map(item => ( Id: item.Id, Name: item.Name ));
const format = e =>
switch (true)
case typeof e === 'boolean': return e ? 'Y' : 'N'
case isNaN(e) && !isNaN(Date.parse(e)):
return new Date(e).toLocaleDateString()
default: return e
const mapped = (arr2.value ?? [0]).map(item => keys.reduce((prev, cur) => (
...prev, [cur.Name]: format(item[cur.Id] ?? '')
), ));
return rows: mapped ;
console.log(mapper(data1, data2));
console.log(mapper(data1, []));
【讨论】:
以上是关于JavaScript:如何映射两个对象以获得将第一个对象的 ID 映射到另一个对象的名称的输出?的主要内容,如果未能解决你的问题,请参考以下文章
Python Pandas:排序和分组,然后将第二列的两个连续行求和以获得第三列的特定值
如何在JavaScript中通过加工一些值来更新第一对象和第二对象。