Pobierz określony obiekt przez id z tablicy obiektów w AngularJS

111

Mam plik JSON zawierający dane, do których chciałbym uzyskać dostęp w mojej witrynie AngularJS. Teraz chcę uzyskać tylko jeden obiekt z tablicy. Więc chciałbym na przykład przedmiot o identyfikatorze 1.

Dane wyglądają następująco:

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

Chciałbym załadować dane za pomocą funkcji AngularJS $ http w następujący sposób:

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

który działa. Ale jak mogę teraz uzyskać określony obiekt danych (według identyfikatora) z tablicy, z której otrzymuję$http.get ?

Z góry dziękuje za twoją pomoc.

Pozdrawia Marc

mooonli
źródło
Czy dałeś temu szansę? Jeśli tak, czy możemy zobaczyć, co wymyśliłeś?
simonlchilds
1
Cóż, nie mam pojęcia, który sposób byłby najlepszy przy użyciu AngularJS. To, co mi się nie podoba, to iterowanie po tablicy i wykonywanie równości na id. Może jest lepszy sposób?
mooonli,
Do takiego przetwarzania należy polegać na podkreśleniach lub podobnych bibliotekach. AngularJS jest frameworkiem MVVM i może nie mieć do tego interfejsu API.
Vijay Pande,
@marcbaur - musisz iterować tablicę. Nawet jeśli użyjesz podkreślenia lub czegoś podobnego, jego funkcje, za kulisami, tylko iterują.
Adam
1
dodaj do tego kod kątowy
Ankush Kondhalkar

Odpowiedzi:

4

Jedynym sposobem na to jest iteracja po tablicy. Oczywiście, jeśli jesteś pewien, że wyniki są uporządkowane według identyfikatora, możesz przeprowadzić wyszukiwanie binarne

Antonio E.
źródło
46
... Naprawdę mam nadzieję, że po przeczytaniu tej odpowiedzi ludzie uważają, że posortowanie tablicy, a następnie wyszukiwanie binarne, nie jest dobrym pomysłem. Wyszukiwanie binarne jest sprytne , ale tylko wtedy, gdy tablica jest już posortowana, aw rzeczywistości jest: 1. łatwa do złej implementacji, 2. trudniejsza do odczytania, jeśli jest źle zaimplementowana.
Ben Lesh,
4
Byłbym bardzo wdzięczny, gdyby osoby osłabiające umotywowały swoją decyzję.
Antonio E.
1
Domyślnie typ tablicy javascript ma metodę find (). Metoda find () zwraca wartość pierwszego elementu tablicy, który spełnia podaną funkcję testującą.
abosancic
246

Korzystanie z rozwiązania ES6

Dla tych, którzy nadal czytają tę odpowiedź, jeśli używasz ES6, plik find metoda została dodana w tablicach. Zakładając więc tę samą kolekcję, rozwiązaniem byłoby:

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

Całkowicie wybrałbym teraz to rozwiązanie, ponieważ jest mniej przywiązane do kątowych lub innych ram. Czysty JavaScript.

Rozwiązanie kątowe (stare rozwiązanie)

Chciałem rozwiązać ten problem, wykonując następujące czynności:

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

Przykład użycia:

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

Willemoes
źródło
1
Właściwie myślę, że tak! Po pobraniu tablicy możesz użyć funkcji $ filter, aby odfiltrować element o poprawnym identyfikatorze.
flup
10
To powinna być akceptowana odpowiedź. Miałem to samo pytanie w mojej głowie i ta odpowiedź jest jedyną, która wykorzystuje istniejący AngularJS i nie wymyśla koła na nowo. I tak, to działa.
Zoran P.
4
+1 za zaakceptowaną odpowiedź. Najlepsze rozwiązanie wykorzystujące biblioteki kątowe.
Meki,
1
Plunker z filtrem w wyrażeniu: plnkr.co/edit/yc0uZejGqWTcUVKvI7Tq?p=preview
Aaron Roller
4
Należy pamiętać, że filtry domyślnie wyszukują podciągi bez rozróżniania wielkości liter. Więc (foo.results, {id: 2}) zwraca [{id: 12}, {id: 2}], {id: 222}] ale (foo.results, function (d) {return d.id == = 2;}) zwraca [{id: 2}]
Ryan.lay
26

Dla każdego, kto przegląda ten stary post, jest to obecnie najłatwiejszy sposób. Wymaga tylko AngularJS $filter. To jak odpowiedź Willemoesa, ale krótsze i łatwiejsze do zrozumienia.

{ 
    "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" }

OSTRZEŻENIE

Jak mówi @mpgn, to nie działa poprawnie . To przyniesie więcej wyników. Przykład: kiedy wyszukujesz 3, to również złapie 23

Tillman32
źródło
1
także catch id: 24 12 222 2002 itd.
mpgn
Wydaje mi się, że [0]zwróciłby pierwszy wynik znaleziony w kolekcji, więc działałby tylko wtedy, gdy twoja kolekcja jest posortowana, a obiekt, którego szukasz, jest pierwszym znalezionym podczas iteracji. Na przykład. jeśli istnieje id: 12, który pojawia się przed id: 2, zwróci id: 12.
Roddy of the Frozen Peas
25

osobiście używam podkreślenia do tego typu rzeczy ... więc

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

wtedy „a” będzie żądanym wierszem w tablicy, w którym identyfikator jest równy 2

Jason Boerner
źródło
1
Ja naprawdę kocham podkreślenia, ale robi to gorzej mający inną bibliotekę JavaScript?
Genuinefafa
8
Zauważ, że findmoże potencjalnie zwrócić wiele obiektów. Ponieważ chcemy tylko jednego, możemy użyć, findWherektóry zwraca tylko pierwsze wystąpienie (o którym wiemy, że jest jedynym wystąpieniem), np a = _.findWhere(results, {id: 2}).
gregoltsov
16

Chcę tylko dodać coś do odpowiedzi Willemoesa . Ten sam kod napisany bezpośrednio w kodzie HTML będzie wyglądał następująco:

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

Zakładając, że „wyniki” to zmienna Twojego FooController i chcesz wyświetlić właściwość „name” przefiltrowanego elementu.

Włącz
źródło
@ Ena-Jak sprawdzić, czy wynik filtru nie jest zerowy lub niezdefiniowany?
Abhijeet
Użyłem tego wariantu HTML, ponieważ byłem pewien, że wynik istnieje. Próbowałem i jak nie ma rezultatu to konsola nie podaje żadnego błędu, po prostu zostawia pusty tekst. Jeśli potrzebujesz trochę logiki, jeśli nie zostanie znaleziony wynik, myślę, że najlepszym sposobem jest odpowiedź Willemoes (kod js w kontrolerze). W tym przykładzie powinieneś następnie sprawdzić w HTML, czy zmienna single_object ma wartość null lub undefined.
Ena
2
{{(FooController.results | filter: {id: 1}) [0] .name}: true} - jeśli ktoś szuka dokładnego dopasowania
George Sharvadze
12

Możesz używać ng-repeati wybierać dane tylko wtedy, gdy są zgodne z tym, czego szukasz, ng-show na przykład:

 <div ng-repeat="data in res.results" ng-show="data.id==1">
     {{data.name}}
 </div>    
James Kuta Simiyu
źródło
2
Jeśli twoja tablica ma więcej niż trywialną liczbę elementów, spowoduje to powstanie wielu niepotrzebnych zakresów, które mogą spowolnić twoją aplikację.
The DIMM Reaper
9

Możesz po prostu zapętlić swoją tablicę:

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);

Jeśli nie chcesz pisać tych niechlujnych pętli, możesz rozważyć użycie underscore.js lub Lo-Dash (przykład w tym drugim):

var doc_id_2 = _.filter(doc.results, {id: 2})[0]
kamituel
źródło
8

Jeśli chcesz wyświetlić listę pozycji, takich jak miasto na podstawie identyfikatora stanu, użyj

var state_Id = 5;
var items = ($filter('filter')(citylist, {stateId: state_Id }));
Ali Adravi
źródło
7

Niestety (o ile się nie mylę), myślę, że musisz powtórzyć obiekt wyników.

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

Przynajmniej w ten sposób wyjdzie z iteracji, gdy tylko znajdzie prawidłowy pasujący identyfikator.

simonlchilds
źródło
Czemu? Czy masz coś na poparcie tego?
simonlchilds
11
Cóż, wiesz co ..? Po prostu poszedł do ponownego odczytania JavaScript - części dobrych przeciwdziałać swój argument, a ja jestem w błędzie! Przez cały ten czas robiłem to źle! Nie sprawiło mi to jednak żadnych problemów ... jeszcze. Zaktualizowałem odpowiedź.
simonlchilds
6

Po co komplikować sytuację? to jest proste, napisz jakąś funkcję taką jak ta:

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 '';
}

Przypadek użycia:

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'));

wynik:

Result is Bərdə filialı
Musa
źródło
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>

wyjście: Azərbaycan

Celal Muhtar
źródło
2

Jeśli możesz, zaprojektuj strukturę danych JSON, używając indeksów tablic jako identyfikatorów. Możesz nawet "znormalizować" swoje tablice JSON, o ile nie masz problemu z używaniem indeksów tablic jako "klucza podstawowego" i "klucza obcego", coś w rodzaju RDBMS. W związku z tym w przyszłości możesz nawet zrobić coś takiego:

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

To jest rozwiązanie „By Design” . W Twoim przypadku po prostu:

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

Oczywiście, jeśli format Twojego identyfikatora jest taki jak „XX-0001”, którego indeks tablicy wynosi 0 , możesz albo wykonać operacje na łańcuchach, aby zmapować identyfikator; w przeciwnym razie nic nie można na to poradzić, z wyjątkiem podejścia iteracyjnego.

Antonio Ooi
źródło
2

Wiem, że jestem za późno na odpowiedź, ale zawsze lepiej jest się pojawić niż w ogóle się nie pojawiać :). ES6 sposób, aby to zdobyć:

$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
});
Hitesh Kumar
źródło
2

Prosty sposób na pobranie (jednego) elementu z tablicy przez id:

Metoda find () zwraca wartość pierwszego elementu tablicy, który spełnia podaną funkcję testującą. W przeciwnym razie zwracany jest undefined.

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

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

nie musisz używać filter () i łapać pierwszego elementu xx.filter () [0] jak w komentarzach powyżej

To samo dotyczy obiektów w tablicy

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);

Oczywiście, jeśli masz wiele identyfikatorów, użyj metody filter (), aby pobrać wszystkie obiekty. Twoje zdrowie

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);

abosancic
źródło
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;
        }
        }

    });
});

Nie jestem pewien, czy to naprawdę dobre, ale to było dla mnie pomocne. Musiałem użyć $ scope, aby działał poprawnie.

Jordy
źródło
0

użyj $ timeout i uruchom funkcję do wyszukiwania w tablicy wyników

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);

    });
Moein Fazeli
źródło
0

Iterowałbym po tablicy wyników za pomocą filtru angularjs w następujący sposób:

var foundResultObject = getObjectFromResultsList (wyniki, 1);

function getObjectFromResultsList(results, resultIdToRetrieve) {
        return $filter('filter')(results, { id: resultIdToRetrieve }, true)[0];
    }
abovetempo
źródło