Sprawdź, czy wartość obiektu istnieje w tablicy obiektów JavaScript, a jeśli nie, dodaj nowy obiekt do tablicy

147

Jeśli mam następującą tablicę obiektów:

[ { id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 2, username: 'ted' } ]

Czy istnieje sposób na zapętlenie tablicy w celu sprawdzenia, czy określona wartość nazwy użytkownika już istnieje i czy nic nie robi, ale jeśli nie, to dodanie nowego obiektu do tablicy ze wspomnianą nazwą użytkownika (i nowym identyfikatorem)?

Dzięki!

user2576960
źródło
1
Czy Bill i Ted powinni mieć ten sam identyfikator?
user2357112 obsługuje Monikę
Dlaczego dwa elementy są takie same id? Czy to możliwe, że elementy zostaną usunięte z tej tablicy, czy też możemy być pewni, że nowy element zawsze będzie miał idrówne arr.length + 1?
raina77ow
Jeśli nie chcesz przez to przechodzić, sprawdź te pytania i odpowiedzi dotyczące rozszerzania prototypu tablicy, stackoverflow.com/questions/1988349/… .
Cem Özer
natywne funkcje są wolniejsze w porównaniu do zwykłych pętli, a ich obsługa jest ograniczona do niektórych wersji przeglądarek. sprawdź moją odpowiedź poniżej.
Zaheen
jest to zasadniczo błędne pytanie, ponieważ możesz to zrobić, unikając stosowania tablic.
Bekim Bacaj

Odpowiedzi:

234

Założyłem, że tutaj idmają być wyjątkowe. someto świetna funkcja do sprawdzania istnienia rzeczy w tablicach:

const arr = [{ id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 3, username: 'ted' }];

function add(arr, name) {
  const { length } = arr;
  const id = length + 1;
  const found = arr.some(el => el.username === name);
  if (!found) arr.push({ id, username: name });
  return arr;
}

console.log(add(arr, 'ted'));

Andy
źródło
1
Dzięki Andy, to bardzo czyste rozwiązanie problemu i działa bardzo dobrze. Nie spotkałem wcześniej jakiejś metody. Twoje założenie było poprawne, mój przykład identyfikacyjny był po prostu literówką, używałem arr.length + 1 do określenia identyfikatora.
user2576960
3
Uważaj, IE8 i wcześniejsze wersje nie obsługują niektórych funkcji.
BetaRide
Czy znalezioną funkcję można przekształcić w IF? Coś w rodzaju: if (arr.some (function (el) {el.Id == someId) i zwróci prawdę lub fałsz, jeśli istnieje lub nie?
stibay

@stibay, some nie zwraca wartość logiczną. foundalbo będzie truealbo falsew zależności od tego, czy warunek w zwrotnego jest spełniony.
Andy

1
Jasne: if (arr.some(function (el) { return el.Id == someId; })) { // do something }. Nie zapomnij o tym, returnbo nic nie odzyskasz.
Andy

26

Sprawdzenie istniejącej nazwy użytkownika jest raczej trywialne:

var arr = [{ id: 1, username: 'fred' }, 
  { id: 2, username: 'bill'}, 
  { id: 3, username: 'ted' }];

function userExists(username) {
  return arr.some(function(el) {
    return el.username === username;
  }); 
}

console.log(userExists('fred')); // true
console.log(userExists('bred')); // false

Ale nie jest takie oczywiste, co zrobić, gdy musisz dodać nowego użytkownika do tej tablicy. Najłatwiejsze wyjście - wystarczy popchnąć nowy element z idrównymi array.length + 1:

function addUser(username) {
  if (userExists(username)) {
    return false; 
  }
  arr.push({ id: arr.length + 1, username: username });
  return true;
}

addUser('fred'); // false
addUser('bred'); // true, user `bred` added

Zagwarantuje to unikalność identyfikatorów, ale sprawi, że tablica będzie wyglądać nieco dziwnie, jeśli niektóre elementy zostaną zdjęte z jej końca.


Dzięki za to. Ostatecznie wybrałem rozwiązanie Andy'ego, ponieważ jest to bardziej zwięzły sposób osiągnięcia tego samego. W żadnym momencie nie będę usuwał użytkowników, więc identyfikatory powinny pozostać spójne. Sprawdzenie umożliwia użytkownikom logowanie, wylogowywanie i ponowne logowanie bez zwiększania liczby tablic w nadgodzinach. Dla informacji używam tej funkcji w połączeniu z passport.js i nie byłem w stanie znaleźć sposobu na usunięcie użytkowników z tablicy bez bawienia się samym kodem paszportowym. To rozwiązanie działa ładnie.
user2576960


10

Myślę, że to najkrótszy sposób rozwiązania tego problemu. Tutaj użyłem funkcji strzałek ES6 z .filter, aby sprawdzić istnienie nowo dodanej nazwy użytkownika.

var arr = [{
    id: 1,
    username: 'fred'
}, {
    id: 2,
    username: 'bill'
}, {
    id: 3,
    username: 'ted'
}];

function add(name) {
    var id = arr.length + 1;        
            if (arr.filter(item=> item.username == name).length == 0){
            arr.push({ id: id, username: name });
        }
}

add('ted');
console.log(arr);

Link do Fiddle


3

To, co zrobiłem, oprócz @ Sagar-gavhane „s odpowiedź

const newUser = {_id: 4, name: 'Adam'}
const users = [{_id: 1, name: 'Fred'}, {_id: 2, name: 'Ted'}, {_id: 3, 'Bill'}]

const userExists = users.some(user => user.name = newUser.name);
if(userExists) {
    return new Error({error:'User exists'})
}
users.push(newUser)

Cześć, jeśli znalazłem wartość, jak mogę uzyskać dostęp do identyfikatora?
Kusal Kithmal

To naprawdę proste... if(userExists) { const userId = userExists.id return userId; } ...
Michael Enitan

2

Zaakceptowaną odpowiedź można również zapisać w następujący sposób używając funkcji strzałek na .some

 function checkAndAdd(name) {
     var id = arr.length + 1;
     var found = arr.some((el) => {
           return el.username === name;
     });
     if (!found) { arr.push({ id: id, username: name }); }
 }

2

Oto łańcuch metod ES6 wykorzystujący .map()i .includes():

const arr = [ { id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 2, username: 'ted' } ]

const checkForUser = (newUsername) => {
      arr.map(user => {
        return user.username
      }).includes(newUsername)
    }

if (!checkForUser('fred')){
  // add fred
}
  1. Mapuj istniejących użytkowników, aby utworzyć tablicę ciągów nazw użytkowników.
  2. Sprawdź, czy ta tablica nazw użytkowników zawiera nową nazwę użytkownika
  3. Jeśli go nie ma, dodaj nowego użytkownika

1

Podoba mi się odpowiedź Andy'ego, ale identyfikator niekoniecznie będzie unikalny, więc oto, co wymyśliłem, aby utworzyć unikalny identyfikator. Można też sprawdzić na jsfiddle . Należy pamiętać, że arr.length + 1może to nie zagwarantować unikalnego identyfikatora, jeśli coś zostało wcześniej usunięte.

var array = [ { id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 3, username: 'ted' } ];
var usedname = 'bill';
var newname = 'sam';

// don't add used name
console.log('before usedname: ' + JSON.stringify(array));
tryAdd(usedname, array);
console.log('before newname: ' + JSON.stringify(array));
tryAdd(newname, array);
console.log('after newname: ' + JSON.stringify(array));

function tryAdd(name, array) {
    var found = false;
    var i = 0;
    var maxId = 1;
    for (i in array) {
        // Check max id
        if (maxId <= array[i].id)
            maxId = array[i].id + 1;

        // Don't need to add if we find it
        if (array[i].username === name)
            found = true;
    }

    if (!found)
        array[++i] = { id: maxId, username: name };
}

Podoba mi się prostota w innych odpowiedziach, właśnie opublikowałem swoją, aby dodać czek na unikalny identyfikator
Uxonith

Dziękuję za odpowiedź Uxonith. W tej chwili nie potrzebuję unikalnego ID, ponieważ nie będę usuwał użytkowników z tablicy. Zachowam to postanowienie w tylnej kieszeni na wypadek, gdyby zaszła taka potrzeba.
Jeszcze

1

Możesz prototypować swoją tablicę, aby była bardziej modularna, spróbuj czegoś takiego

    Array.prototype.hasElement = function(element) {
        var i;
        for (i = 0; i < this.length; i++) {
            if (this[i] === element) {
                return i; //Returns element position, so it exists
            }
        }

        return -1; //The element isn't in your array
    };

Możesz go używać jako:

 yourArray.hasElement(yourArrayElement)

1

Z jakiegoś powodu wypróbowałem powyższe kroki, wydaje się, że nie działają one dla mnie, ale to było moje ostateczne rozwiązanie mojego własnego problemu, może być pomocne dla każdego, kto to przeczytał:

let pst = post.likes.some( (like) => {  //console.log(like.user, req.user.id);
                                     if(like.user.toString() === req.user.id.toString()){
                                         return true
                                     } } )

tutaj post.likes to tablica użytkowników, którzy polubili post.


1

Spróbuj tego

pierwsza metoda przy użyciu niektórych plików

  let arr = [{ id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 3, username: 'ted' }];
    let found = arr.some(ele => ele.username === 'bill');
    console.log(found)

druga metoda wykorzystująca include, map

   let arr = [{ id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 3, username: 'ted' }];
    let mapped = arr.map(ele => ele.username);
    let found = mapped.includes('bill');
    console.log(found)

A jeśli chcę porównać obiekty z dwoma atrybutami, takimi jak {"name": "test1", "age": 30}?
probitaille
1

Załóżmy, że mamy tablicę obiektów i chcesz sprawdzić, czy wartość nazwy jest zdefiniowana w ten sposób,

let persons = [ {"name" : "test1"},{"name": "test2"}];

if(persons.some(person => person.name == 'test1')) {
    ... here your code in case person.name is defined and available
}
Hasan Zahran
źródło
Dodaj kilka zdań, aby wyjaśnić, co robi Twój kod, aby uzyskać więcej głosów pozytywnych za swoją odpowiedź.
Analiza rozmyta
A jeśli chcę porównać obiekty z dwoma atrybutami, takimi jak {"name": "test1", "age": 30}?
probitaille
0

Natywne funkcje tablicy są czasami 3X - 5X razy wolniejsze niż zwykłe pętle. Dodatkowo natywne funkcje nie będą działać we wszystkich przeglądarkach, więc występują problemy ze zgodnością.

Mój kod:

<script>
  var obj = [];

  function checkName(name) {
    // declarations
    var flag = 0;
    var len = obj.length;   
    var i = 0;
    var id = 1;

    // looping array
    for (i; i < len; i++) {
        // if name matches
        if (name == obj[i]['username']) {
            flag = 1;
            break;
        } else {
            // increment the id by 1
            id = id + 1;
        }
    }

    // if flag = 1 then name exits else push in array
    if (flag == 0) {
      // new entry push in array        
      obj.push({'id':id, 'username': name});
    }
  }
  // function end

  checkName('abc');
</script>

W ten sposób możesz szybciej osiągnąć wynik.

Uwaga: Nie sprawdzałem, czy przekazany parametr jest pusty, czy nie, jeśli chcesz, możesz go zaznaczyć lub napisać wyrażenie regularne dla określonej walidacji.

Zaheen
źródło
0

xorWith w Lodash można to osiągnąć

let objects = [ { id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 2, username: 'ted' } ]
let existingObject = { id: 1, username: 'fred' };
let newObject = { id: 1729, username: 'Ramanujan' }

_.xorWith(objects, [existingObject], _.isEqual)
// returns [ { id: 2, username: 'bill' }, { id: 2, username: 'ted' } ]

_.xorWith(objects, [newObject], _.isEqual)
// returns [ { id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 2, username: 'ted' } ,{ id: 1729, username: 'Ramanujan' } ]
sudo bangbang
źródło
0

function number_present_or_not () { var arr = [ 2,5,9,67,78,8,454,4,6,79,64,688 ] ; znaleziono var = 6; var found_two; dla (i = 0; i

    }
    if ( found_two == found )
    {
        console.log("number present in the array");
    }
    else
    {
        console.log("number not present in the array");
    }
}
Nakkeeran 8797
źródło
-1

Oto najlepsza praktyka.

var arr = ["a","b","c","d"];
console.log(arr.includes("a")); //---- true;
console.log(arr.includes("k")); //---- false;
console.log(arr.includes("c")); //---- true;
Niebieski deszcz
źródło
18
Pytanie dotyczy tablicy obiektów, a to nie zadziała.
Adrian Enriquez,
to nie jest właściwa odpowiedź na to pytanie.
Ahsan Mukhtar
ta odpowiedź nie wystarcza na wymóg, o którym mowa w pytaniu.
Savan Gadhiya