当我需要一个复合键来区分它时,如何创建一个不同的 javascript 对象列表?
How can I create a distinct list of javascript objects, when I need a compound key to make it distinct?
是的,有几篇关于用多种语言创建不同列表的帖子,但我没有看到任何关于使用复合键或复合键的帖子。
我有一组重复的对象(联系人),我需要从中创建一个不同值的数组,键是 电子邮件名称的组合和 phone 个字段。对象看起来像这样:
{
name: "Name",
email: "email@example.com",
phone: "5551212",
organization: "BigCompany",
title: "CEO"
}
我可以使用 map.has() 创建一个不同的列表,仅基于电子邮件:
const distinct = [];
const map = new Map();
for (const item of contacts) {
if(!map.has(item.email)){
map.set(item.email, true); // set any value, but add an entry to the Map
distinct.push(item);
}
}
...但是我需要为每个联系人使用不同的数组元素,使用相同的电子邮件,但不同的 phone,或相同的 phone,但不同的电子邮件等。阅读文档map.has()
,我没有看到关于关键参数是复杂数据结构(在本例中为多个字段)的任何信息。有没有更好的工具,或者我只是错过了文档的那一部分?
您可以创建一个 JSON 字符串用作键,如下所示:
const distinct = [];
const map = new Map();
for (const item of contacts) {
const {name, email, phone} = item;
const key = JSON.stringify({name, email, phone});
if(!map.has(key){
map.set(key, true);
distinct.push(item);
}
}
因为 JSON.stringify
(spec | MDN) 需要遵循 ES2015 的 属性 顺序(许多操作不是),你知道如果你以相同的方式创建对象每次并且所有可枚举属性都是 "own" 属性,对于具有相同 name
、email
和 [=15= 的对象,生成的 JSON 字符串将是相同的] 属性 值(如果不同则不同)。 ("create the objects in the same way every time" 很重要,对象 {a: 1, b: 2}
和 {b: 2, a: 1}
导致 不同的 JSON 字符串。)
旁注:如果您只使用 map.has
和 map.set(key, true)
,Set
可能更有意义:
const distinct = [];
const set = new Set();
for (const item of contacts) {
const {name, email, phone} = item;
const key = JSON.stringify({name, email, phone});
if(!set.has(key){
set.add(key);
distinct.push(item);
}
}
您可以使用 Map
通过创建您自己的复合键来存储您的不同联系人:
const contacts = [
{
name: "Name",
email: "email@example.com",
phone: "5551212",
organization: "BigCompany",
title: "CEO"
},
// ...
]
// Store distinct contacts.
const map = new Map()
contacts.forEach((c) => {
/**
* Any contact with the same name, email, and phone will
* be considered a duplicate.
*/
const key = `${c.name}::${c.email}::${c.phone}`
map.set(key, c)
})
现在您的地图是项目的容器 { key => contact }
。
要获取不同联系人的列表,请使用:
const list = Array.from(map.values())
// Use spread syntax to accoplish the same thing.
const list2 = [...map.values()]
注意:如果姓名、电子邮件或 phone 号码可能包含该子字符串,则使用分隔符 ::
可能被认为是不安全的。无论您使用哪个定界符,您都应该确保在可能的情况下禁止在这些字段中输入它,and/or 使其在输入中出现的可能性极小:
const delim = '__:DELIM:__'
const key = `${c.name}${delim}${c.email}${delim}${c.phone}`
即便如此,也不能 100% 保证分隔符不会出现在 name
等字段中,除非您对该字段执行输入验证。
编辑:检查T.J。 Crowder 的 JSON 密钥,使用该方法生成您的密钥可以很好地保证没有子字符串问题:
const key = JSON.stringify({name, email, phone});
map.set(key, c)
是的,有几篇关于用多种语言创建不同列表的帖子,但我没有看到任何关于使用复合键或复合键的帖子。
我有一组重复的对象(联系人),我需要从中创建一个不同值的数组,键是 电子邮件名称的组合和 phone 个字段。对象看起来像这样:
{
name: "Name",
email: "email@example.com",
phone: "5551212",
organization: "BigCompany",
title: "CEO"
}
我可以使用 map.has() 创建一个不同的列表,仅基于电子邮件:
const distinct = [];
const map = new Map();
for (const item of contacts) {
if(!map.has(item.email)){
map.set(item.email, true); // set any value, but add an entry to the Map
distinct.push(item);
}
}
...但是我需要为每个联系人使用不同的数组元素,使用相同的电子邮件,但不同的 phone,或相同的 phone,但不同的电子邮件等。阅读文档map.has()
,我没有看到关于关键参数是复杂数据结构(在本例中为多个字段)的任何信息。有没有更好的工具,或者我只是错过了文档的那一部分?
您可以创建一个 JSON 字符串用作键,如下所示:
const distinct = [];
const map = new Map();
for (const item of contacts) {
const {name, email, phone} = item;
const key = JSON.stringify({name, email, phone});
if(!map.has(key){
map.set(key, true);
distinct.push(item);
}
}
因为 JSON.stringify
(spec | MDN) 需要遵循 ES2015 的 属性 顺序(许多操作不是),你知道如果你以相同的方式创建对象每次并且所有可枚举属性都是 "own" 属性,对于具有相同 name
、email
和 [=15= 的对象,生成的 JSON 字符串将是相同的] 属性 值(如果不同则不同)。 ("create the objects in the same way every time" 很重要,对象 {a: 1, b: 2}
和 {b: 2, a: 1}
导致 不同的 JSON 字符串。)
旁注:如果您只使用 map.has
和 map.set(key, true)
,Set
可能更有意义:
const distinct = [];
const set = new Set();
for (const item of contacts) {
const {name, email, phone} = item;
const key = JSON.stringify({name, email, phone});
if(!set.has(key){
set.add(key);
distinct.push(item);
}
}
您可以使用 Map
通过创建您自己的复合键来存储您的不同联系人:
const contacts = [
{
name: "Name",
email: "email@example.com",
phone: "5551212",
organization: "BigCompany",
title: "CEO"
},
// ...
]
// Store distinct contacts.
const map = new Map()
contacts.forEach((c) => {
/**
* Any contact with the same name, email, and phone will
* be considered a duplicate.
*/
const key = `${c.name}::${c.email}::${c.phone}`
map.set(key, c)
})
现在您的地图是项目的容器 { key => contact }
。
要获取不同联系人的列表,请使用:
const list = Array.from(map.values())
// Use spread syntax to accoplish the same thing.
const list2 = [...map.values()]
注意:如果姓名、电子邮件或 phone 号码可能包含该子字符串,则使用分隔符 ::
可能被认为是不安全的。无论您使用哪个定界符,您都应该确保在可能的情况下禁止在这些字段中输入它,and/or 使其在输入中出现的可能性极小:
const delim = '__:DELIM:__'
const key = `${c.name}${delim}${c.email}${delim}${c.phone}`
即便如此,也不能 100% 保证分隔符不会出现在 name
等字段中,除非您对该字段执行输入验证。
编辑:检查T.J。 Crowder 的 JSON 密钥,使用该方法生成您的密钥可以很好地保证没有子字符串问题:
const key = JSON.stringify({name, email, phone});
map.set(key, c)