Как изменить значение объекта Array в Javascript

У меня есть вызов объекта массива listOfObjects.

[{"name":"A", "data":"[{"value1":"1","value2":"2"}]"},
 {"name":"B", "data":"[{"value1":"1","value2":"2"}]"}]

Что я хочу сделать, так это вставить объект в массив, где массив пуст. Если массив не пуст, проверьте элемент внутри. Если элемент уже существует, обновите элемент, иначе добавьте его в массив. Ниже мой код

  var searchName= "A"; 
  if (listOfObjects.length > 0) {
            for (var i = 0; i < listOfObjects.length; i++) {
                if (listOfObjects[i].name == searchName) {
                    listOfObjects[i].data = data;
                    break;
                } else {
                    insert = {
                        'name': searchName,
                        'data': data
                    };
                    listOfObjects.push(insert);
                }
            }
    } else {
        insert = {
            'name': searchName,
            'data': data
        };
        listOfObjects.push(insert);
   }

Когда я запускаю его, хотя A уже существует, он обновляет существующий элемент, но также добавляет еще раз в listOfObjects. Есть ли способ достичь того, чего я хочу? Спасибо..


person Xion    schedule 16.01.2018    source источник
comment
Вы обернули свой внутренний массив в "", что означает, что это строка, а не массив   -  person Arun P Johny    schedule 16.01.2018


Ответы (4)


Проблема в том, что вы вставляете в массив внутри своего цикла for в поисках совпадения. Вместо этого вспомните, видели ли вы совпадение, и вставьте после цикла, если вы этого не сделали. Также нет причин для проверки length и нет причин повторять вашу логику для вставки:

var searchName= "A"; 
var found = false;
for (var i = 0; !found && i < listOfObjects.length; i++) {
    if (listOfObjects[i].name == searchName) {
        listOfObjects[i].data = data;
        found = true;
    }
}
if (!found) {
    listOfObjects.push({
        'name': searchName,
        'data': data
    });
}

Обратите внимание, что вы можете использовать Array#find (который может быть заполнен для старых браузеров), чтобы найти запись, а не цикл for, если хотите:

var searchName= "A"; 
var entry = listOfObjects.find(function(entry) {
    return entry.name == searchName;
});
if (entry) {
    entry.data = data;
} else {
    listOfObjects.push({
        'name': searchName,
        'data': data
    });
}
person T.J. Crowder    schedule 16.01.2018

Прежде всего измените это

[{"name":"A", "data":"[{"value1":"1","value2":"2"}]"},
 {"name":"B", "data":"[{"value1":"1","value2":"2"}]"}]

by

[{"name":"A", "data":[{"value1":1,"value2":2}]},
 {"name":"B", "data":[{"value1":"1","value2":"2"}]}];

потому что ваш список будет throw Uncaught SyntaxError: Unexpected identifier

person DHARMENDRA SINGH    schedule 16.01.2018

Напишите еще одну простую функцию для получения элемента listOfObjects[i] с выбранным searchName. Здесь функция getSearchObject() проверяет наличие searchName, а затем добавляет или обновляет массив.

addOrRemoveItem() {
    let listOfObjects = [
      { "name": "A", "data": "[{'value1':'1','value2':'2'}]" },
      { "name": "B", "data": "[{'value1':'1','value2':'2'}]" }
    ],
      data = '[{"value1":"1","value2":"2"}]';
    var searchName = "C";
    if (listOfObjects.length > 0) {
      let searchObj = this.getSearchObject(listOfObjects, searchName);
      if (searchObj) {
        searchObj.data = data;
      } else {
        let insert = {
          "name": searchName,
          "data": data
        }
        listOfObjects.push(insert);
      }
    } else {
      let insert = {
        "name": searchName,
        "data": data
      }
      listOfObjects.push(insert);
    }
  }

  getSearchObject(objArr, searchKey) {
    var obj = null;
    for (let i = 0; i < objArr.length; i++) {
      if (objArr[i].name === searchKey) {
        obj = objArr[i];
      }
    }
    return obj;
  }
person Anu Sivanand    schedule 16.01.2018

Общее решение, которое распознает старые JS-движки (filter вместо find), но всегда предполагает передачу списка уникальных элементов, может быть реализовано следующим образом...

function updateList(itemList, item) { // - always assume a list of unique items.
  var
    itemName = item.name,
    listItem = itemList.filter(function (elm) { // - assume `filter`, not find`.
      return (elm.name === itemName); // - find/get existing list  item by name.
    })[0];

  if (listItem) {
    listItem.data = item.data;
  } else {
    itemList.push(item)
  }
}


var list = [
  { "name": "A", "data": [ { "value1": "A1", "value2": "A2" }] },
  { "name": "B", "data": [ { "value1": "B1", "value2": "B2" }] },
  { "name": "C", "data": [ { "value1": "C1", "value2": "C2" }] }
];

console.log('list : ', list);


updateList(list,  { "name": "D", "data": [ { "value1": "D1", "value2": "D2" }] });

updateList(list,  { "name": "B", "data": [ { "value1": "b_1", "value2": "b_2", "value3": "b_3" }] });
updateList(list,  { "name": "C", "data": [ { "value3": "C3" }] });

console.log('list : ', list);
.as-console-wrapper { max-height: 100%!important; top: 0; }

person Peter Seliger    schedule 16.01.2018