2014-09-10 11 views
11

Więc mam tablicę obiektów tak:Aktualizacja jeśli istnieje, lub dodać nowy element do tablicy obiektów - elegancki sposób w javascript + lodash

var arr = [ 
    {uid: 1, name: "bla", description: "cucu"}, 
    {uid: 2, name: "smth else", description: "cucarecu"}, 
] 

uid jest unikalny identyfikator obiektu w tej tablicy. Szukam eleganckiego sposobu modyfikacji obiektu, jeśli mamy obiekt z danym uid, lub dodać nowy element, jeśli prezentowany uid nie istnieje w tablicy. Wyobrażam sobie, że funkcja będzie zachowywać się tak w js konsoli:

> addOrReplace(arr, {uid: 1, name: 'changed name', description: "changed description"}) 
> arr 
[ 
    {uid: 1, name: "bla", description: "cucu"}, 
    {uid: 2, name: "smth else", description: "cucarecu"}, 
] 
> addOrReplace(arr, {uid: 3, name: 'new element name name', description: "cocoroco"}) 
> arr 
[ 
    {uid: 1, name: "bla", description: "cucu"}, 
    {uid: 2, name: "smth else", description: "cucarecu"}, 
    {uid: 3, name: 'new element name name', description: "cocoroco"} 
] 

Mój obecny sposób nie wydaje się być bardzo elegancki i funkcjonalny:

function addOrReplace (arr, object) { 
    var index = _.findIndex(arr, {'uid' : object.uid}); 
    if (-1 === index) { 
    arr.push(object); 
    } else { 
    arr[index] = object; 
    } 
} 

Używam lodash, więc jestem myślenie o zmodyfikowanej wersji _.union z niestandardowym sprawdzaniem równości.

Odpowiedz

8

Można użyć obiektu zamiast array:

var hash = { 
    '1': {uid: 1, name: "bla", description: "cucu"}, 
    '2': {uid: 2, name: "smth else", description: "cucarecu"} 
}; 

Klucze są identyfikatorami UID. Teraz twoja funkcja addOrReplace jest prosta tak:

function addOrReplace(hash, object) { 
    hash[object.uid] = object; 
} 

UPDATE

Możliwe jest również, aby użyć obiektu jako wskaźnik oprócz tablicy.
ten sposób masz szybkich wyszukiwań a także tablicę pracy:

var arr = [], 
    arrIndex = {}; 

addOrReplace({uid: 1, name: "bla", description: "cucu"}); 
addOrReplace({uid: 2, name: "smth else", description: "cucarecu"}); 
addOrReplace({uid: 1, name: "bli", description: "cici"}); 

function addOrReplace(object) { 
    var index = arrIndex[object.uid]; 
    if(index === undefined) { 
     index = arr.length; 
     arrIndex[object.uid] = index; 
    } 
    arr[index] = object; 
} 

spojrzeć na jsfiddle-demo (roztwór obiektowego znajdą Państwo here)

+0

tak, też podoba mi się ta struktura, ale niektóre biblioteki których używam nie Wspieraj to. Podobnie jak [Angular typeahead] (https://github.com/angular-ui/bootstrap/tree/master/src/typeahead), który może przechodzić tylko przez tablice. – ganqqwerty

+1

Możesz użyć tej struktury tylko jako indeksu. W ten sposób uzyskujesz szybkie wyszukiwanie i potrzebna jest dodatkowa tablica dla takich elementów, jak tablica. – friedi

1

Co posiadające indeksy tablicy samo jak uid, jak:

arr = []; 
arr[1] = {uid: 1, name: "bla", description: "cucu"}; 
arr[2] = {uid: 2, name: "smth else", description: "cucarecu"}; 

że sposób można po prostu użyć

arr[affectedId] = changedObject; 
+0

będzie działać dobrze, jeśli mam gwarancję, że uuid jest zawsze int. Myślę, że czasami tak nie jest. Ale nawet jeśli mam tę gwarancję, czuję się niekomfortowo, gdy mam tablice z brakującymi elementami: 'arr [2134], arr [2135]', gdy arr [0] nie istnieje. – ganqqwerty

+0

@ yqqqwerty tak powstała klasyczna tablica użyj asocjatywnego (obiektu), w ten sposób można użyć indeksów niecałkowitych i nie mają "dziur" w twojej tablicy – Drecker

3

Może

_.mixin({ 
    mergeById: function mergeById(arr, obj, idProp) { 
     var index = _.findIndex(arr, function (elem) { 
      // double check, since undefined === undefined 
      return typeof elem[idProp] !== "undefined" && elem[idProp] === obj[idProp]; 
     }); 

     if (index > -1) { 
      arr[index] = obj; 
     } else { 
      arr.push(obj); 
     } 

     return arr; 
    } 
}); 

i

var elem = {uid: 3, name: 'new element name name', description: "cocoroco"}; 

_.mergeById(arr, elem, "uid"); 
3

Stary post, ale dlaczego nie skorzystać z funkcji filtra?

// If you find the index of an existing uid, save its index then delete it 
//  --- after the filter add the new object. 
function addOrReplace(argh, obj) { 
    var index = -1; 
    argh.filter((el, pos) => { 
    if(el.uid == obj.uid) 
     delete argh[index = pos]; 
    return true; 
    }); 

    // put in place, or append to list 
    if(index == -1) 
    argh.push(obj); 
    else 
    argh[index] = obj; 
} 

Oto jsfiddle pokazujący jak to działa.

Powiązane problemy