Как сгенерировать динамический идентификатор для объекта JavaScript при вставке нового элемента?

У меня есть массив элементов объекта JavaScript внутри. Вот пример:

var contacts =[{"id":1,"first":"Mike","last":"Johnson","email":"[email protected]","phone":"(203) 567-9055","status":1},{"id":2,"first":"John","last":"Dunn","email":"[email protected]","phone":"(319) 451-7889","status":1},{"id":3,"first":"Lisa","last":"Morgan","email":"[email protected]","phone":"(508) 233-8908","status":1},{"id":4,"first":"Dave","last":"Hart","email":"[email protected]","phone":"(509) 874-9411","status":1}];

Мне нужно вставлять/обновлять записи в этот массив. Я не уверен, что лучше всего проверить, существует ли запись в этом массиве. Если существует, обновите объект js, если нет, создайте новый id. В идеале этот идентификатор должен быть целым числом и начинаться после самого высокого текущего идентификатора в объекте js. Таким образом, в приведенных выше данных наибольшее значение идентификатора равно 4. Если я вставлю новую запись id, новая запись должна быть 5. Есть ли хороший способ добиться этого с помощью JavaScript?

function saveContact(){
    var frmObject = $(this),
        frmKey = $("#frm_id").val(),
        formData = frmObject.serialize(),
        contactRecord = contacts.find(item => item.id === Number(frmKey));;

        if (contactRecord) {
            contacts[frmKey] = getJSON(frmObject.serializeArray()); // If already exist in array then update object
        }else{
            frmKey = 'generate new id';
            contacts[frmKey] = getJSON(frmObject.serializeArray()); // If doesn't exist generate new key and insert object in array 
        }
}

person espresso_coffee    schedule 02.08.2018    source источник
comment
Похоже, с вашим кодом было бы намного проще работать, если бы вы могли использовать объект объектов (индексированный по идентификатору) вместо массива объектов - это вариант? Использование .find каждый раз не кажется лучшей идеей. (Не имеет значения на самом деле, но код будет чище)   -  person CertainPerformance    schedule 02.08.2018
comment
@CertainPerformance Объект объектов - это вариант, поэтому, если вы можете привести пример того, как сгенерировать id, это самая важная часть для меня.   -  person espresso_coffee    schedule 02.08.2018


Ответы (5)


Это было упомянуто в комментарии, но я немного конкретизирую.

Если ваши данные представляют собой объект с идентификатором, а не массивом, это заставит идентификаторы быть уникальными, поскольку объекты должны иметь уникальные ключи.

Например:

var contacts =[{"id":1,"first":"Mike","last":"Johnson","email":"[email protected]","phone":"(203) 567-9055","status":1},{"id":2,"first":"John","last":"Dunn","email":"[email protected]","phone":"(319) 451-7889","status":1},{"id":3,"first":"Lisa","last":"Morgan","email":"[email protected]","phone":"(508) 233-8908","status":1},{"id":4,"first":"Dave","last":"Hart","email":"[email protected]","phone":"(509) 874-9411","status":1}];

// just a quick dirty conversion
let obj = contacts.reduce((a, c) => (a[c.id] = c, a), {})

//Object looks like:
console.log(obj)

// find the largest key // maybe a good way to decide the next key
largest_id = Math.max(...Object.keys(obj))
console.log("largest ID", largest_id)

// is ID 4 taken?
console.log("is there a 4", 4 in obj) //yes
// alternatively obj.hasOwnProperty('4')

// is 5?
console.log("is there a 5", 5 in obj) //no

// update ID 4:
obj['4'].first = "Mark"
console.log(obj['4'])

Надеюсь, это немного побудит попробовать этот подход вместо массива.

person Mark    schedule 02.08.2018
comment
Я попробовал предложенное вами решение, используя Math.max(Object.keys(obj)), но оно вернуло NaN, вместо этого я использовал этот код Object.keys(obj).reduce((a, b) => obj[a] > obj[b] ? a : b);, а он вернул 4. Есть ли у вас мнение об использовании метода reduce() для этой цели? - person espresso_coffee; 02.08.2018
comment
Я думаю, что сокращение — это хорошо, но его цель немного менее очевидна визуально. Похоже, что в вашем Math.max отсутствует оператор распространения .... - person Mark; 02.08.2018
comment
... что требуется? Я думал, что это просто комментарий. Никогда такого раньше не видел. - person espresso_coffee; 02.08.2018
comment
@espresso_coffee Да, чтобы использовать Math.max вот так, вам это нужно. Он разбивает массив на отдельные значения, превращая что-то вроде Math.max( [1, 2, 3] ) в Math.max( 1, 2, 3 ). - person Mark; 02.08.2018
comment
Очень интересно, я только что проверил и отлично работает. Кроме того, это вернет тип number по сравнению с моим решением, использующим reduce, возвращает тип string. Спасибо за вашу помощь. - person espresso_coffee; 02.08.2018

Найдите последний объект в массиве и получите его идентификатор:

contacts[contacts.length-1].id

Затем просто добавьте 1, и вы получите следующий идентификационный номер.

person dandeto    schedule 02.08.2018
comment
В случае, если я решу использовать объект объектов, какое решение будет в этом случае? Я не могу использовать .length для объектов, так есть ли другой способ найти длину объекта? - person espresso_coffee; 02.08.2018
comment
Вы можете получить последний ключ, но это зависит от того, как вы структурируете объект. Прочтите это: stackoverflow.com/questions/4317456/ Если бы вы могли привести пример того, как будет выглядеть объект, я был бы рад дать вам больше рекомендаций! - person dandeto; 02.08.2018
comment
Я нашел этот подход и, похоже, работает нормально var test = Object.keys(contacts).reduce((a, b) => contacts[a] > contacts[b] ? a : b); возвращает самое высокое значение ключа. Поэтому я просто добавляю +1 для создания нового ключа для моего объекта. Спасибо за вашу помощь! - person espresso_coffee; 02.08.2018

Вы можете создать глобальную переменную и использовать ее как счетчик, каждый раз для новой записи вы можете увеличивать ее на единицу, для существующих просто обновлять.

Вы можете хранить все json в базе данных, во время выборки просто подсчитайте элементы массива/идентификатор последнего элемента и установите его в счетчике.

Кроме того, если вам не нужен автоматически сгенерированный идентификатор в последовательности, вы также можете использовать случайную функцию для создания уникального идентификатора каждый раз.

person Lokesh Verma    schedule 02.08.2018

Вы можете добиться этого простым способом, если будете управлять своими данными как объектом объектов.

var contacts  = {

   
  1: {
    first: "Mike",
    last: "Johnson",    
    email:"[email protected]",
    phone:"(203) 567-9055",
    status:"1"
 },
  2: {
    first: "John",
    last: "Dunn",    
    email:"[email protected]",
    phone:"(319) 451-7889",
    status:"1"
 },
  3: {
    first: "Lisa",
    last: "Morgan",    
    email:"[email protected]",
    phone:"(508) 233-8908",
    status:"1"
 },
  4: {
    first: "Dave",
    last: "Hart",    
    email:"[email protected]",
    phone:"(509) 874-9411",
    status:"1"
 }
};

var frmKey = 5;
if(contacts[frmKey]){
console.log(contacts[frmKey]);
 // If already exist in array then update object
}else{
  contacts[frmKey] = {first: "Lisa1",last: "Morgan1", email:"[email protected]", phone:"(508) 233-8908", status:"1" };

  console.log("Added New Key::"+frmKey,contacts[frmKey]);

}

person NullPointer    schedule 02.08.2018

Вы можете использовать Object для хранения Collection of Objects. Каждый раз, когда объект вводится в коллекцию, генерируется новый идентификатор (на основе длины коллекции), если id объекта, вставленного в коллекцию, уже существует, он выполняет только обновление.

const collection = {};

function insert(obj){
   // if id is set in object and object is already in Collection... 
   if(obj.id && collection.hasOwnProperty(obj.id) ){ 
     // Update object!
     collection[obj.id]= Object.assign(collection[ obj.id], obj) ;
   }else{ 
     // if provided object has no ID... generate it!
     if( !obj.id ) obj.id = Object.keys(collection).length;
     // insert provided object to collection;
     collection[obj.id]= obj;
   }
   // return generaed id;
   return obj.id;
}


// Let's test...

let obj_1 ={"first":"Mike","last":"Johnson","email":"[email protected]","phone":"(203) 567-9055","status":1};

let obj_2 = {"first":"John","last":"Dunn","email":"[email protected]","phone":"(319) 451-7889","status":1};

// insert bth object
insert(obj_1);
insert(obj_2);
// perform a change in object 2
obj_2.first ='Joseph';
// insert object 2 again...
insert(obj_2);
// object 2 has been updated, and all have unique ids
console.log(collection);

person colxi    schedule 02.08.2018
comment
Конечно, но как узнать, есть ли в наборе id:1. Кажется маловероятным, что у вас будет ссылка на точный объект, когда вы захотите его обновить. - person Mark; 02.08.2018
comment
извините, я неправильно понял ваш вопрос. я обновил свой ответ, используя лучший подход - person colxi; 02.08.2018