我知道已经有一个similar question 了,但是我的不同之处在于我只是不想找到它,我只想更新它
我有一个这样的对象的JS数组:
let data = [
{
contact_id: 15,
use_id: 16,
name: 'ABC',
phoneNo: '0092123456789',
checked: false,
},
{
contact_id: 16,
use_id: 22,
name: 'DEF',
phoneNo: '0092123456788',
checked: false,
},
{
contact_id: 17,
use_id: 24,
name: 'XYZ',
phoneNo: '0092123456787',
checked: false,
}
];
现在牢记这一点,我有一个名为phoneNo
的属性,它保证了唯一的值。
现在,我要为给定数字切换checked
的值。
我尝试过的事情:
for (let i = 0; i < data.length; i++) {
if (data[i]['phoneNo'] === item.phoneNo) {
data[i]['checked'] = !data[i]['checked'];
break; // to make it a little efficent :-)
}
}
我编写了这段代码,并在一段时间内运行良好,但现在我意识到列表越来越大,并且这段代码反复迭代,这效率很低。
我想要什么?
在给定checked
的值的情况下,是否可以直接切换属性phoneNo
的值而无需遍历每个项目?
答案 0 :(得分:3)
另一个选择是更改数据存储方式。如果phoneNo
是唯一的,则可以使用电话号码作为密钥来进行数据。
let data2={
'0092123456789':{
contact_id: 15,
use_id: 16,
name: 'ABC',
checked: false,
},
'0092123456788':{
contact_id: 16,
use_id: 22,
name: 'DEF',
checked: false,
},
'0092123456787':{
contact_id: 17,
use_id: 24,
name: 'XYZ',
checked: false,
}};
myPhoneNo = '0092123456787';
data2[myPhoneNo].checked = true;
console.log(data2);
答案 1 :(得分:2)
在给定phoneNo值的情况下,是否可以直接切换所检查属性的值而无需遍历每个项目?
不是您当前的结构。但是您可以使用Map
代替数组(或在数组之外),这很简单:
const entry = mappedData.get(item.phoneNo);
entry.checked = !entry.checked;
如果您需要遍历地图的值,则可以使用其values
方法中的迭代器,例如:
for (const entry of mappedData) {
// ...
}
如果您只有一张地图,并且由于某种原因需要获取值数组,则可以将values()
与扩展符号一起使用:
const data = [...mappedData.values()];
这是一个仅使用地图但不使用数组并循环遍历地图值的示例:
// ONE TIME, add and remove entries as needed
let mappedData = new Map([
{
contact_id: 15,
use_id: 16,
name: 'ABC',
phoneNo: '0092123456789',
checked: false,
},
{
contact_id: 16,
use_id: 22,
name: 'DEF',
phoneNo: '0092123456788',
checked: false,
},
{
contact_id: 17,
use_id: 24,
name: 'XYZ',
phoneNo: '0092123456787',
checked: false,
}
].map(entry => [entry.phoneNo, entry]));
console.log("Before:");
for (const {phoneNo, checked} of mappedData.values()) {
console.log(`${phoneNo}: ${checked}`);
}
// Each time you want to toggle
let phoneNo = '0092123456788';
console.log(`Checking ${phoneNo}...`);
let entry = mappedData.get(phoneNo);
entry.checked = !entry.checked;
console.log("After:");
for (const {phoneNo, checked} of mappedData.values()) {
console.log(`${phoneNo}: ${checked}`);
}
与在访问时间是线性的数组中搜索不同,对Map条目的访问时间必须是次线性的(通过使用哈希映射或类似方法实现)。
答案 2 :(得分:2)
您可以创建一个对象,其键将是电话号码,值将是将引用数组data
中的对象的对象
const obj = {}
let data = [ { contact_id: 15, use_id: 16, name: 'ABC', phoneNo: '0092123456789', checked: false, }, { contact_id: 16, use_id: 22, name: 'DEF', phoneNo: '0092123456788', checked: false, }, { contact_id: 17, use_id: 24, name: 'XYZ', phoneNo: '0092123456787', checked: false, } ];
data.forEach(x => {
obj[x.phoneNo] = x;
})
let given = '0092123456788';
obj[given].checked = !obj[given].checked
console.log(data)
答案 3 :(得分:1)
如果知道对象的索引,则只需一行即可更改它。但是,如果数组更改了对象的索引,则必须循环。
答案 4 :(得分:0)
否,您必须知道要在数组中更改的元素的索引,或者遍历所有项以找到与您要查找的项相匹配的项。
答案 5 :(得分:0)
您必须迭代数组。但是,您可以通过仅先找到匹配的索引来缩短循环时间。您可以先使用给定的phoneNo查找对象,然后切换值。尝试以下代码:
''' const matchData = data.find(x => x.phoneNo === item.phoneNo) matchData.checked =!matchData.checked '''
答案 6 :(得分:0)
非常简单而且非常快速
var data = [{
contact_id: 15,
use_id: 16,
name: 'ABC',
phoneNo: '0092123456789',
checked: false,
},
{
contact_id: 16,
use_id: 22,
name: 'DEF',
phoneNo: '0092123456788',
checked: false,
},
{
contact_id: 17,
use_id: 24,
name: 'XYZ',
phoneNo: '0092123456787',
checked: false,
}],
result = data.some(function(x){return '0092123456787'==x.phoneNo ? true:false});
console.log(result);