Lấy đối tượng cụ thể theo id từ mảng đối tượng trong AngularJS


111

Tôi có một tệp JSON chứa một số dữ liệu tôi muốn truy cập trên trang web AngularJS của mình. Bây giờ những gì tôi muốn là chỉ lấy một đối tượng từ mảng. Vì vậy, tôi muốn ví dụ Mục có id 1.

Dữ liệu trông như thế này:

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

Tôi muốn tải dữ liệu với chức năng AngularJS $ http như thế này:

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

đang hoạt động. Nhưng làm cách nào bây giờ tôi có thể lấy một đối tượng dữ liệu cụ thể (theo id) từ mảng tôi lấy từ đó $http.get?

Cảm ơn trước sự giúp đỡ của bạn.

Greets Marc


Bạn đã thử cho mình chưa? Nếu vậy, chúng tôi có thể xem bạn đã nghĩ ra gì không?
simonlchilds

1
Tôi không biết cách nào là tốt nhất khi sử dụng AngularJS. Những gì tôi không thích là lặp lại trên mảng và thực hiện một dấu bằng trên id. Có lẽ có một cách tốt hơn?
mooonli

Bạn nên dựa vào underscorejs hoặc các thư viện tương tự để xử lý như vậy. AngularJS là khuôn khổ MVVM và có thể không có api cho việc này.
Vijay Pande

@marcbaur - bạn phải lặp lại mảng. Ngay cả khi bạn sử dụng dấu gạch dưới hoặc một cái gì đó tương tự, các chức năng của nó, đằng sau hậu trường, chỉ đang lặp lại.
Adam

1
xin vui lòng thêm mã góc cho điều này
Ankush Kondhalkar

Câu trả lời:


4

Cách duy nhất để làm điều này là lặp qua mảng. Rõ ràng nếu bạn chắc chắn rằng kết quả được sắp xếp theo id, bạn có thể thực hiện tìm kiếm nhị phân


46
... Tôi thực sự hy vọng sau khi đọc câu trả lời này, mọi người không nghĩ rằng việc sắp xếp một mảng sau đó thực hiện tìm kiếm nhị phân là một ý kiến ​​hay. Tìm kiếm nhị phân là thông minh , chắc chắn, nhưng chỉ khi mảng đã được sắp xếp, và trên thực tế là: 1. dễ triển khai kém, 2. Khó đọc hơn nếu thực hiện kém.
Ben Lesh

4
Tôi sẽ đánh giá rất cao nếu những người phản đối có thể thúc đẩy quyết định của họ.
Antonio E.

1
Theo mặc định javascript Kiểu mảng có phương thức find (). Phương thức find () trả về giá trị của phần tử đầu tiên trong mảng thỏa mãn hàm kiểm tra được cung cấp.
tàu vào

246

Sử dụng giải pháp ES6

Đối với những người vẫn đọc câu trả lời này, nếu bạn đang sử dụng ES6, findphương thức đã được thêm vào các mảng. Vì vậy, giả sử cùng một bộ sưu tập, giải pháp sẽ là:

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

Tôi hoàn toàn muốn giải pháp này ngay bây giờ, vì ít bị ràng buộc vào góc cạnh hoặc bất kỳ khuôn khổ nào khác. Javascript thuần túy.

Giải pháp góc cạnh (giải pháp cũ)

Tôi đã cố gắng giải quyết vấn đề này bằng cách làm như sau:

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

Một ví dụ về trường hợp sử dụng:

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
Trên thực tế, tôi nghĩ nó có! Sau khi tìm nạp mảng, bạn có thể sử dụng hàm $ filter để lọc ra mục có id chính xác.
flup

10
Đây phải là câu trả lời được chấp nhận. Tôi đã có cùng một câu hỏi trong đầu và câu trả lời này là câu trả lời duy nhất sử dụng AngularJS hiện có và không phải là phát minh lại bánh xe. Và có, nó đang hoạt động.
Zoran P.

4
+1 cho đây là câu trả lời được chấp nhận. Giải pháp tốt nhất bằng cách sử dụng thư viện góc.
Meki

1
Plunker với bộ lọc trong một biểu thức: plnkr.co/edit/yc0uZejGqWTcUVKvI7Tq?p=preview
Aaron Roller

4
Lưu ý rằng các bộ lọc tìm các chuỗi con không phân biệt chữ hoa chữ thường theo mặc định. Vì vậy, (foo.results, {id: 2}) trả về [{id: 12}, {id: 2}], {id: 222}] nhưng (foo.results, function (d) {return d.id == = 2;}) trả về [{id: 2}]
Ryan.lay

26

Đối với bất kỳ ai đang xem bài đăng cũ này, đây là cách dễ nhất để thực hiện hiện tại. Nó chỉ yêu cầu một AngularJS $filter. Nó giống như câu trả lời của Willemoes, nhưng ngắn hơn và dễ hiểu hơn.

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

CẢNH BÁO

Như @mpgn nói, điều này không hoạt động đúng . Điều này sẽ thu được nhiều kết quả hơn. Ví dụ: khi bạn tìm kiếm 3 cái này cũng sẽ bắt được 23


1
cũng bắt được id: 24 12 222 2002 vv
mpgn 22/09/2016

Tôi nghĩ rằng điều đó [0]sẽ khiến nó trả về kết quả đầu tiên mà nó tìm thấy từ bộ sưu tập, vì vậy nó sẽ chỉ hoạt động nếu bộ sưu tập của bạn được sắp xếp và đối tượng bạn đang tìm kiếm là đối tượng đầu tiên nó tìm thấy trong quá trình lặp lại. Ví dụ. nếu có một id: 12 mà đến trước id: 2, nó sẽ quay trở lại id: 12.
Roddy của Frozen Peas

25

cá nhân tôi sử dụng dấu gạch dưới cho loại công cụ này ... vì vậy

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

thì "a" sẽ là hàng mà bạn muốn trong mảng của mình nơi id bằng 2


1
Tôi thực sự yêu dấu gạch dưới, nhưng liệu có tệ hơn khi có một thư viện JavaScript khác không?
hãngfafa

8
Lưu ý rằng findcó thể trả về nhiều đối tượng. Vì chúng ta chỉ muốn một, chúng ta có thể sử dụng findWheremà chỉ trả lại sự xuất hiện đầu tiên (mà chúng tôi biết là sự xuất hiện duy nhất), ví dụ a = _.findWhere(results, {id: 2}).
gregoltsov

16

Tôi chỉ muốn thêm một cái gì đó vào câu trả lời của Willemoes . Cùng một đoạn mã được viết trực tiếp bên trong HTML sẽ giống như sau:

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

Giả sử rằng "kết quả" là một biến của FooController của bạn và bạn muốn hiển thị thuộc tính "tên" của mục được lọc.


@ Ena-Làm thế nào để kiểm tra kết quả của bộ lọc không rỗng hoặc không xác định?
Abhijeet

Tôi đã sử dụng biến thể HTML này vì tôi chắc chắn rằng có một kết quả tồn tại. Tôi đã thử và nếu không có kết quả, bảng điều khiển không đưa ra bất kỳ lỗi nào, nó chỉ để trống văn bản. Nếu bạn cần thực hiện một số logic nếu không tìm thấy kết quả thì tôi nghĩ cách tốt nhất để đi là câu trả lời Willemoes (mã js bên trong bộ điều khiển). Trong ví dụ đó, bạn nên kiểm tra trong HTML nếu biến single_object là null hoặc undefined.
Ena

2
{{(FooController.results | filter: {id: 1}) [0] .name}: true} - nếu ai đó đang tìm kiếm một kết quả phù hợp chính xác
George Sharvadze

12

Bạn chỉ có thể sử dụng ng-repeatvà chọn dữ liệu nếu dữ liệu khớp với những gì bạn đang tìm kiếm, ng-show ví dụ:

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

2
Nếu mảng của bạn có nhiều hơn một số lượng mục nhỏ, điều này sẽ tạo ra nhiều phạm vi không cần thiết có thể làm chậm ứng dụng của bạn.
The DIMM Reaper

9

Bạn chỉ có thể lặp lại mảng của mình:

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

Nếu bạn không muốn viết các vòng lặp lộn xộn này, bạn có thể xem xét sử dụng underscore.js hoặc Lo-Dash (ví dụ trong phần sau):

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

8

Nếu bạn muốn danh sách các mục như thành phố trên cơ sở id tiểu bang thì hãy sử dụng

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

7

Thật không may (trừ khi tôi nhầm), tôi nghĩ bạn cần phải lặp lại đối tượng kết quả.

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

Ít nhất bằng cách này, nó sẽ thoát ra khỏi vòng lặp ngay khi tìm thấy id phù hợp chính xác.


Tại sao? Bạn có gì để sao lưu điều đó không?
simonlchilds

11
Chà, bạn biết gì không ..? Tôi chỉ bắt đầu đọc lại Javascript - những phần tốt để phản bác lại lập luận của bạn và tôi đã sai! Trong suốt thời gian qua, tôi đã làm sai! Tuy nhiên, nó vẫn chưa gây ra cho tôi bất kỳ vấn đề nào. Tôi đã cập nhật câu trả lời của mình.
simonlchilds

6

Tại sao lại làm phức tạp tình hình? điều này rất đơn giản, hãy viết một số hàm như sau:

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

Trường hợp sử dụng:

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

đầu ra:

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>

đầu ra: Azərbaycan


2

Nếu bạn có thể, hãy thiết kế cấu trúc dữ liệu JSON của bạn bằng cách sử dụng các chỉ mục mảng làm ID. Bạn thậm chí có thể "bình thường hóa" các mảng JSON của mình miễn là bạn không gặp vấn đề gì khi sử dụng các chỉ mục mảng làm "khóa chính" và "khóa ngoại", giống như RDBMS. Như vậy, trong tương lai, bạn thậm chí có thể làm điều gì đó như sau:

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

Đây là giải pháp "Theo thiết kế" . Đối với trường hợp của bạn, chỉ cần:

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

Tất nhiên, nếu định dạng ID của bạn giống như "XX-0001" trong đó chỉ số mảng của nó là 0 , thì bạn có thể thực hiện một số thao tác chuỗi để ánh xạ ID; hoặc không thể làm gì khác ngoại trừ cách tiếp cận lặp lại.


2

Tôi biết tôi đã quá muộn để trả lời nhưng tốt hơn là nên xuất hiện hơn là không hiển thị gì cả :). ES6 cách để có được nó:

$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

Cách đơn giản để lấy (một) phần tử từ mảng theo id:

Phương thức find () trả về giá trị của phần tử đầu tiên trong mảng thỏa mãn hàm kiểm tra được cung cấp. Nếu không, không xác định được trả lại.

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

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

bạn không cần sử dụng filter () và bắt phần tử đầu tiên xx.filter () [0] như trong các nhận xét ở trên

Tương tự đối với các đối tượng trong mảng

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

Tất nhiên nếu bạn có nhiều id thì hãy sử dụng phương thức filter () để lấy tất cả các đối tượng. Chúc mừng

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

    });
});

Không chắc liệu nó có thực sự tốt hay không, nhưng điều này rất hữu ích cho tôi .. Tôi cần sử dụng $ scope để làm cho nó hoạt động bình thường.


0

sử dụng $ timeout và chạy một hàm để tìm kiếm trong mảng "kết quả"

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

Tôi sẽ lặp lại mảng kết quả bằng cách sử dụng bộ lọc anglejs như sau:

var foundResultObject = getObjectFromResultsList (kết quả, 1);

function getObjectFromResultsList(results, resultIdToRetrieve) {
        return $filter('filter')(results, { id: resultIdToRetrieve }, true)[0];
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.