Ottieni un oggetto specifico per id dall'array di oggetti in AngularJS


111

Ho un file JSON contenente alcuni dati a cui vorrei accedere sul mio sito Web AngularJS. Ora quello che voglio è ottenere un solo oggetto dall'array. Quindi mi piacerebbe ad esempio Item con ID 1.

I dati hanno questo aspetto:

{ "results": [
    {
        "id": 1,
        "name": "Test"
    },
    {
        "id": 2,
        "name": "Beispiel"
    },
    {
        "id": 3,
        "name": "Sample"
    }
] }

Mi piacerebbe caricare i dati con la funzionalità AngularJS $ http in questo modo:

$http.get("data/SampleData.json");

che funziona. Ma come posso ora ottenere un oggetto dati specifico (per id) dall'array da cui ottengo $http.get?

Grazie in anticipo per il vostro aiuto.

Saluta Marc


Hai provato tu stesso? Se è così, possiamo vedere cosa hai pensato?
simonlchilds

1
Beh, non ho idea in quale modo sarebbe il migliore usando AngularJS. Quello che non mi piace è iterare sull'array e fare un uguale sull'id. Forse c'è un modo migliore?
mooonli

Dovresti fare affidamento su underscorejs o librerie simili per tale elaborazione. AngularJS è un framework MVVM e potrebbe non avere API per questo.
Vijay Pande

@marcbaur - devi iterare l'array. Anche se usi il carattere di sottolineatura o qualcosa di simile, le sue funzioni, dietro le quinte, sono solo iteranti.
Adam

1
si prega di aggiungere un codice angolare per questo
Ankush Kondhalkar

Risposte:


4

L'unico modo per farlo è iterare sull'array. Ovviamente se sei sicuro che i risultati siano ordinati per id puoi fare una ricerca binaria


46
... Spero davvero che dopo aver letto questa risposta la gente non pensi che sia una buona idea ordinare un array e poi fare una ricerca binaria. La ricerca binaria è intelligente , certo, ma solo se l'array è già ordinato, e in realtà è: 1. facile da implementare male, 2. più difficile da leggere se implementato male.
Ben Lesh

4
Apprezzerei molto se i downvoters potessero motivare la loro decisione.
Antonio E.

1
Per impostazione predefinita, il tipo di array javascript ha il metodo find (). Il metodo find () restituisce il valore del primo elemento dell'array che soddisfa la funzione di test fornita.
abosancic

246

Utilizzando la soluzione ES6

Per coloro che stanno ancora leggendo questa risposta, se si utilizza ES6 il findmetodo è stato aggiunto in array. Quindi, supponendo la stessa raccolta, la soluzione sarebbe:

const foo = { "results": [
    {
        "id": 12,
        "name": "Test"
    },
    {
        "id": 2,
        "name": "Beispiel"
    },
    {
        "id": 3,
        "name": "Sample"
    }
] };
foo.results.find(item => item.id === 2)

Preferirei totalmente questa soluzione ora, poiché è meno legata a angular o qualsiasi altro framework. Javascript puro.

Soluzione angolare (vecchia soluzione)

Ho mirato a risolvere questo problema facendo quanto segue:

$filter('filter')(foo.results, {id: 1})[0];

Un esempio di caso d'uso:

app.controller('FooCtrl', ['$filter', function($filter) {
    var foo = { "results": [
        {
            "id": 12,
            "name": "Test"
        },
        {
            "id": 2,
            "name": "Beispiel"
        },
        {
            "id": 3,
            "name": "Sample"
        }
    ] };

    // We filter the array by id, the result is an array
    // so we select the element 0

    single_object = $filter('filter')(foo.results, function (d) {return d.id === 2;})[0];

    // If you want to see the result, just check the log
    console.log(single_object);
}]);

Plunker: http://plnkr.co/edit/5E7FYqNNqDuqFBlyDqRh?p=preview


1
In realtà, penso di sì! Dopo aver recuperato l'array, puoi usare la funzione $ filter per filtrare l'elemento con l'id corretto.
flup

10
Questa dovrebbe essere la risposta accettata. Avevo la stessa domanda nella mia testa e questa risposta è l'unica che utilizza AngularJS esistente e non sta reinventando la ruota. E sì, funziona.
Zoran P.

4
+1 perché questa è la risposta accettata. La migliore soluzione utilizzando le librerie angolari.
Meki

1
Plunker con filtro in un'espressione: plnkr.co/edit/yc0uZejGqWTcUVKvI7Tq?p=preview
Aaron Roller

4
Tieni presente che i filtri trovano per impostazione predefinita sottostringhe senza distinzione tra maiuscole e minuscole. Quindi (foo.results, {id: 2}) restituisce [{id: 12}, {id: 2}], {id: 222}] ma (foo.results, funzione (d) {return d.id == = 2;}) restituisce [{id: 2}]
Ryan.lay

26

Per chiunque guardi questo vecchio post, questo è il modo più semplice per farlo attualmente. Richiede solo un AngularJS $filter. È come la risposta di Willemoes, ma più breve e più facile da capire.

{ 
    "results": [
        {
            "id": 1,
            "name": "Test"
        },
        {
            "id": 2,
            "name": "Beispiel"
        },
        {
            "id": 3,
            "name": "Sample"
        }
    ] 
}

var object_by_id = $filter('filter')(foo.results, {id: 2 })[0];
// Returns { id: 2, name: "Beispiel" }

AVVERTIMENTO

Come dice @mpgn, questo non funziona correttamente . Questo otterrà più risultati. Esempio: quando cerchi 3, anche questo prenderà 23


1
anche catch id: 24
12222

Penso che [0]ciò causerebbe la restituzione del primo risultato che trova dalla raccolta, quindi funzionerebbe solo se la tua raccolta è ordinata e l'oggetto che stai cercando è il primo che trova durante la sua iterazione. Per esempio. se c'è un id: 12 che viene prima di id: 2, restituirà id: 12.
Roddy of the Frozen Peas

25

personalmente uso il carattere di sottolineatura per questo genere di cose ... quindi

a = _.find(results,function(rw){ return rw.id == 2 });

quindi "a" sarebbe la riga che volevi del tuo array dove l'id era uguale a 2


1
Mi piace molto di sottolineatura, ma, fa peggio avere un altro libreria JavaScript?
genuinefafa

8
Tieni presente che findpotenzialmente può restituire più oggetti. Poiché ne vogliamo solo uno, possiamo usare findWhereche restituisce solo la prima occorrenza (che sappiamo essere l'unica occorrenza), ad es a = _.findWhere(results, {id: 2}).
gregoltsov

16

Voglio solo aggiungere qualcosa alla risposta di Willemoes . Lo stesso codice scritto direttamente all'interno dell'HTML avrà questo aspetto:

{{(FooController.results | filter : {id: 1})[0].name }}

Supponendo che "risultati" sia una variabile del tuo FooController e desideri visualizzare la proprietà "nome" dell'elemento filtrato.


@ Ena-Come controllare che il risultato del filtro non sia nullo o indefinito?
Abhijeet,

Ho usato questa variante HTML perché ero sicuro che esistesse un risultato. Ho provato e se non ci sono risultati la console non dà alcun errore, semplicemente lascia il testo vuoto. Se hai bisogno di fare un po 'di logica se non viene trovato alcun risultato, penso che il modo migliore per andare sia la risposta di Willemoes (codice js all'interno del controller). In questo esempio, dovresti quindi controllare in HTML se la variabile single_object è nulla o non definita.
Ena

2
{{(FooController.results | filter: {id: 1}) [0] .name}: true} - se qualcuno sta cercando una corrispondenza esatta
George Sharvadze

12

Puoi utilizzare ng-repeate selezionare i dati solo se i dati corrispondono a ciò che stai cercando, ng-show ad esempio:

 <div ng-repeat="data in res.results" ng-show="data.id==1">
     {{data.name}}
 </div>    

2
Se il tuo array ha più di un numero insignificante di elementi, questo creerà molti ambiti non necessari che potrebbero rallentare la tua applicazione.
The DIMM Reaper

9

Puoi semplicemente eseguire il loop sul tuo array:

var doc = { /* your json */ };

function getById(arr, id) {
    for (var d = 0, len = arr.length; d < len; d += 1) {
        if (arr[d].id === id) {
            return arr[d];
        }
    }
}

var doc_id_2 = getById(doc.results, 2);

Se non vuoi scrivere questo loop disordinato, puoi prendere in considerazione l'utilizzo di underscore.js o Lo-Dash (esempio in quest'ultimo):

var doc_id_2 = _.filter(doc.results, {id: 2})[0]

8

Se vuoi l'elenco di elementi come città sulla base dell'ID dello stato, usa

var state_Id = 5;
var items = ($filter('filter')(citylist, {stateId: state_Id }));

7

Sfortunatamente (a meno che non mi sbagli), penso che sia necessario iterare sull'oggetto risultati.

for(var i = 0; i < results.length; i += 1){
    var result = results[i];
    if(result.id === id){
        return result;
    }
}

Almeno in questo modo uscirà dall'iterazione non appena troverà l'id corrispondente.


Perché? Hai qualcosa a sostegno di questo?
simonlchilds

11
Beh, sai cosa ..? Ho appena andato fuori di rileggere Javascript - i pezzi buoni per contrastare la vostra discussione e mi sono sbagliato! Per tutto questo tempo ho sbagliato! Non mi ha causato alcun problema però ... ancora. Ho aggiornato la mia risposta.
simonlchilds

6

Perché complicare la situazione? questo è semplice scrivere una funzione come questa:

function findBySpecField(data, reqField, value, resField) {
    var container = data;
    for (var i = 0; i < container.length; i++) {
        if (container[i][reqField] == value) {
            return(container[i][resField]);
        }
    }
    return '';
}

Caso d'uso:

var data=[{
            "id": 502100,
            "name": "Bərdə filialı"
        },
        {
            "id": 502122
            "name": "10 saylı filialı"
        },
        {
            "id": 503176
            "name": "5 sayli filialı"
        }]

console.log('Result is  '+findBySpecField(data,'id','502100','name'));

produzione:

Result is Bərdə filialı

4
$scope.olkes = [{'id':11, 'name':'---Zəhmət olmasa seçim edin---'},
                {'id':15, 'name':'Türkyə'},
                {'id':45, 'name':'Azərbaycan'},
                {'id':60, 'name':'Rusya'},
                {'id':64, 'name':'Gürcüstan'},
                {'id':65, 'name':'Qazaxıstan'}];

<span>{{(olkes | filter: {id:45})[0].name}}</span>

uscita: Azərbaycan


2

Se puoi, progetta la tua struttura dati JSON utilizzando gli indici dell'array come ID. Puoi anche "normalizzare" i tuoi array JSON finché non hai problemi a utilizzare gli indici dell'array come "chiave primaria" e "chiave esterna", qualcosa come RDBMS. In quanto tale, in futuro, puoi persino fare qualcosa del genere:

function getParentById(childID) {
var parentObject = parentArray[childArray[childID].parentID];
return parentObject;
}

Questa è la soluzione "By Design" . Per il tuo caso, semplicemente:

var nameToFind = results[idToQuery - 1].name;

Ovviamente, se il formato del tuo ID è qualcosa come "XX-0001" di cui il suo indice di matrice è 0 , puoi eseguire qualche manipolazione delle stringhe per mappare l'ID; oppure non si può fare nulla al riguardo se non attraverso l'approccio dell'iterazione.


2

So di essere in ritardo per rispondere ma è sempre meglio presentarsi piuttosto che non presentarsi affatto :). Modo ES6 per ottenerlo:

$http.get("data/SampleData.json").then(response => {
let id = 'xyz';
let item = response.data.results.find(result => result.id === id);
console.log(item); //your desired item
});

2

Il modo più semplice per ottenere (un) elemento dall'array per id:

Il metodo find () restituisce il valore del primo elemento dell'array che soddisfa la funzione di test fornita. In caso contrario, viene restituito undefined.

function isBigEnough(element) {
    return element >= 15;
}

var integers = [12, 5, 8, 130, 160, 44];
integers.find(isBigEnough); // 130  only one element - first

non è necessario utilizzare filter () e catturare il primo elemento xx.filter () [0] come nei commenti sopra

Lo stesso per gli oggetti nell'array

var foo = {
"results" : [{
    "id" : 1,
    "name" : "Test"
}, {
    "id" : 2,
    "name" : "Beispiel"
}, {
    "id" : 3,
    "name" : "Sample"
}
]};

var secondElement = foo.results.find(function(item){
    return item.id == 2;
});

var json = JSON.stringify(secondElement);
console.log(json);

Ovviamente se hai più id, usa il metodo filter () per ottenere tutti gli oggetti. Saluti

function isBigEnough(element) {
    return element >= 15;
}

var integers = [12, 5, 8, 130, 160, 44];
integers.find(isBigEnough); // 130  only one element - first

var foo = {
"results" : [{
    "id" : 1,
    "name" : "Test"
}, {
    "id" : 2,
    "name" : "Beispiel"
}, {
    "id" : 3,
    "name" : "Sample"
}
]};

var secondElement = foo.results.find(function(item){
    return item.id == 2;
});

var json = JSON.stringify(secondElement);
console.log(json);


0
    projectDetailsController.controller('ProjectDetailsCtrl', function ($scope, $routeParams, $http) {
    $http.get('data/projects.json').success(function(data) {

        $scope.projects = data;
        console.log(data);

        for(var i = 0; i < data.length; i++) {
        $scope.project = data[i];
        if($scope.project.name === $routeParams.projectName) {
            console.log('project-details',$scope.project);
        return $scope.project;
        }
        }

    });
});

Non sono sicuro che sia davvero buono, ma questo è stato utile per me .. Avevo bisogno di usare $ scope per farlo funzionare correttamente.


0

usa $ timeout ed esegui una funzione per cercare nell'array "results"

app.controller("Search", function ($scope, $timeout) {
        var foo = { "results": [
          {
             "id": 12,
             "name": "Test"
          },
          {
             "id": 2,
             "name": "Beispiel"
          },
          {
             "id": 3,
            "name": "Sample"
          }
        ] };
        $timeout(function () {
            for (var i = 0; i < foo.results.length; i++) {
                if (foo.results[i].id=== 2) {
                    $scope.name = foo.results[i].name;
                }
            }
        }, 10);

    });

0

Vorrei iterare sull'array dei risultati usando un filtro angularjs come questo:

var foundResultObject = getObjectFromResultsList (risultati, 1);

function getObjectFromResultsList(results, resultIdToRetrieve) {
        return $filter('filter')(results, { id: resultIdToRetrieve }, true)[0];
    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.