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


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


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


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


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


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.


@ 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>    

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]

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

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.


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ı

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


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.


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

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


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.


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

    });

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];
    }
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.