简体   繁体   中英

How to update JS object value inside an array without looping?

I know that there is a similar question already answered, but mine is different in a way that I just don't want to find it, I just want to update it

I have a JS array of objects like this:

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,
  }
];

Now with this in mind, I have a property named phoneNo which guaranteed unique values.

Now what I want is to toggle the value of checked for a given number.

What I have tried:

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 :-)
    }
}

I wrote this code and it worked fine for a while but now I have realized that the list is growing larger and larger and this code iterates over and over again, which is very inefficient.

What I want?

Is there a way that I could directly toggle the value of the property checked given the value of phoneNo without looping over every single item?

Another option is to change the way your data is stored. If phoneNo is unique you could make data with phone numbers being the keys.

 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); 

Is there a way that I could directly toggle the value of the property checked given the value of phoneNo without looping over every single item?

Not with your current structure. But you can use a Map instead of (or in addition to) the array, and then it's trivial:

const entry = mappedData.get(item.phoneNo);
entry.checked = !entry.checked;

If you need to loop through the map's values, you can use the iterator from its values method, for instance:

for (const entry of mappedData) {
    // ...
}

If you have just a map and need to get an array of values for some reason, you can use values() with spread notation:

const data = [...mappedData.values()];

Here's an example using just a map, without the array, and looping through the map's 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}`); } 

Unlike searching an array, where the access time is linear, access time to a Map's entries is required to be sublinear (achieved by using hash maps or similar).

You can create an object whose keys will be the phone numbers and values will be object that will refer the object in the array 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) 

If you know the index of the object then you can just change it in 1 line. How ever, if the array changes the index of the object then you have to loop.

不,您必须知道要在数组中更改的元素的索引,或循环遍历所有项目以找到与您要查找的内容匹配的元素。

You have to iterate the array. But you can shorten your loop by only finding the matching index first. You can find the object with the given phoneNo first and then toggle the value. Try the following code:

''' const matchData = data.find(x => x.phoneNo === item.phoneNo) matchData.checked = !matchData.checked '''

Very simple and Very fast

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);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM