รับวัตถุเฉพาะโดย id จากอาร์เรย์ของวัตถุใน AngularJS


111

ฉันมีไฟล์ JSON ที่มีข้อมูลบางอย่างที่ฉันต้องการเข้าถึงบนเว็บไซต์ AngularJS ของฉัน ตอนนี้สิ่งที่ฉันต้องการคือรับวัตถุเพียงชิ้นเดียวจากอาร์เรย์ ดังนั้นฉันจึงชอบตัวอย่าง Item ที่มี id 1

ข้อมูลมีลักษณะดังนี้:

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

ฉันต้องการโหลดข้อมูลด้วยฟังก์ชัน AngularJS $ http ดังนี้:

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

ซึ่งใช้งานได้ แต่ตอนนี้ฉันจะรับออบเจ็กต์ข้อมูลเฉพาะ (โดย id) จากอาร์เรย์ที่ฉันได้รับมาได้$http.getอย่างไร

ขอบคุณล่วงหน้าสำหรับความช่วยเหลือของ.

ทักทาย Marc


คุณได้ไปเองหรือไม่? ถ้าเป็นเช่นนั้นเราจะเห็นสิ่งที่คุณคิดขึ้นมาหรือไม่?
simonlchilds

1
ฉันไม่รู้ว่าวิธีใดจะดีที่สุดโดยใช้ AngularJS สิ่งที่ฉันไม่ชอบคือการทำซ้ำบนอาร์เรย์และทำการเท่ากับ id อาจจะมีวิธีที่ดีกว่านี้?
mooonli

คุณควรใช้เครื่องหมายขีดล่างหรือไลบรารีที่คล้ายกันในการประมวลผลดังกล่าว AngularJS เป็นเฟรมเวิร์ก MVVM และอาจไม่มี api สำหรับสิ่งนี้
Vijay Pande

@marcbaur - คุณต้องวนซ้ำอาร์เรย์ แม้ว่าคุณจะใช้เครื่องหมายขีดล่างหรือสิ่งที่คล้ายกัน แต่ฟังก์ชันเบื้องหลังก็เป็นเพียงการทำซ้ำ
อดัม

1
โปรดเพิ่มรหัสเชิงมุมสำหรับสิ่งนี้
Ankush Kondhalkar

คำตอบ:


4

วิธีเดียวที่จะทำได้คือทำซ้ำบนอาร์เรย์ แน่นอนว่าถ้าคุณแน่ใจว่าผลลัพธ์เรียงลำดับตาม id คุณสามารถค้นหาไบนารีได้


46
... ฉันหวังเป็นอย่างยิ่งว่าหลังจากอ่านคำตอบนี้ผู้คนไม่คิดว่าเป็นความคิดที่ดีที่จะจัดเรียงอาร์เรย์จากนั้นทำการค้นหาแบบไบนารี การค้นหาแบบไบนารีนั้นฉลาดแน่นอน แต่เฉพาะในกรณีที่เรียงลำดับอาร์เรย์แล้วและในความเป็นจริงคือ 1. ใช้งานง่ายไม่ดี 2. อ่านยากกว่าหากใช้งานไม่ดี
Ben Lesh

4
ฉันจะขอบคุณเป็นอย่างยิ่งหากผู้ลงคะแนนสามารถกระตุ้นการตัดสินใจของพวกเขาได้
Antonio E.

1
โดยค่าเริ่มต้นประเภทอาร์เรย์ javascript จะมี method find () วิธี find () ส่งคืนค่าขององค์ประกอบแรกในอาร์เรย์ที่ตรงตามฟังก์ชันการทดสอบที่ให้มา
abosancic

246

ใช้โซลูชัน ES6

สำหรับผู้ที่ยังคงอ่านคำตอบนี้หากคุณใช้ ES6 findวิธีนี้จะถูกเพิ่มในอาร์เรย์ ดังนั้นสมมติว่าคอลเลกชันเดียวกันคำตอบจะเป็น:

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

ตอนนี้ฉันจะไปหาวิธีแก้ปัญหานี้โดยสิ้นเชิงเพราะผูกติดกับเชิงมุมหรือกรอบอื่น ๆ Javascript บริสุทธิ์

โซลูชันเชิงมุม (โซลูชันเก่า)

ฉันตั้งเป้าที่จะแก้ปัญหานี้โดยทำสิ่งต่อไปนี้:

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

ตัวอย่างกรณีการใช้งาน:

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
ที่จริงฉันคิดว่ามัน! หลังจากดึงอาร์เรย์แล้วคุณสามารถใช้ฟังก์ชัน $ filter เพื่อกรองรายการด้วย id ที่ถูกต้อง
flup

10
นี่ควรเป็นคำตอบที่ได้รับการยอมรับ ฉันมีคำถามเดียวกันในหัวของฉันและคำตอบนี้เป็นคำตอบเดียวที่ใช้ AngularJS ที่มีอยู่และไม่ได้คิดค้นล้อใหม่ และใช่มันใช้งานได้
Zoran P.

4
+1 เพื่อเป็นคำตอบที่ยอมรับ ทางออกที่ดีที่สุดโดยใช้ไลบรารีเชิงมุม
เมกิ

1
Plunker พร้อมตัวกรองในนิพจน์: plnkr.co/edit/yc0uZejGqWTcUVKvI7Tq?p=preview
Aaron Roller

4
โปรดทราบว่าตัวกรองจะค้นหาโดยใช้สตริงย่อยที่ไม่คำนึงถึงตัวพิมพ์เล็กและใหญ่ตามค่าเริ่มต้น ดังนั้น (foo.results, {id: 2}) จะคืนค่า [{id: 12}, {id: 2}], {id: 222}] แต่ (foo.results, function (d) {return d.id == = 2;}) ส่งคืน [{id: 2}]
Ryan.lay

26

สำหรับใครที่ดูโพสต์เก่า ๆ นี้เป็นวิธีที่ง่ายที่สุดในปัจจุบัน ต้องใช้ AngularJS $filterเท่านั้น มันเหมือนกับคำตอบของ Willemoes แต่สั้นและเข้าใจง่ายกว่า

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

คำเตือน

ในฐานะที่เป็น @mpgn กล่าวนี้ทำงานไม่ถูกต้อง ซึ่งจะได้ผลลัพธ์มากขึ้น ตัวอย่าง: เมื่อคุณค้นหา 3 สิ่งนี้จะจับ 23 ด้วย


1
จับ id: 24
12222

ฉันคิดว่า[0]สาเหตุจะส่งคืนผลลัพธ์แรกที่พบจากคอลเล็กชันดังนั้นจึงใช้ได้เฉพาะเมื่อคอลเล็กชันของคุณถูกจัดเรียงและวัตถุที่คุณกำลังมองหาเป็นสิ่งแรกที่พบในระหว่างการทำซ้ำ เช่น. หากมี id: 12 ที่มาก่อน id: 2 มันจะส่งคืน id: 12
Roddy of the Frozen Peas

25

โดยส่วนตัวฉันใช้ขีดล่างสำหรับสิ่งประเภทนี้ ...

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

จากนั้น "a" จะเป็นแถวที่คุณต้องการสำหรับอาร์เรย์ของคุณโดยที่ id เท่ากับ 2


1
ฉันชอบขีดล่างมาก แต่การมีไลบรารี JavaScript อื่นจะแย่กว่านี้หรือไม่?
Genuinefafa

8
โปรดทราบว่าfindอาจส่งคืนวัตถุหลายชิ้น เนื่องจากเราเพียงต้องการหนึ่งที่เราสามารถใช้findWhereซึ่งผลตอบแทนที่เกิดขึ้นครั้งแรก (ซึ่งเรารู้ก็คือการเกิดขึ้นเท่านั้น) a = _.findWhere(results, {id: 2})เช่น
gregoltsov

16

ผมแค่อยากจะเพิ่มสิ่งที่คำตอบ Willemoes รหัสเดียวกันที่เขียนโดยตรงภายใน HTML จะมีลักษณะดังนี้:

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

สมมติว่า "ผลลัพธ์" เป็นตัวแปรของ FooController ของคุณและคุณต้องการแสดงคุณสมบัติ "name" ของรายการที่กรอง


@ Ena- วิธีตรวจสอบผลลัพธ์ของตัวกรองว่าไม่เป็นโมฆะหรือไม่ได้กำหนด?
Abhijeet

ฉันใช้ตัวแปร HTML นี้เพราะฉันแน่ใจว่ามีผลลัพธ์อยู่ ฉันลองแล้วและหากไม่มีผลลัพธ์คอนโซลไม่ให้ข้อผิดพลาดใด ๆ มันก็ปล่อยข้อความว่างไว้ หากคุณต้องการใช้ตรรกะบางอย่างหากไม่พบผลลัพธ์ฉันคิดว่าวิธีที่ดีที่สุดคือคำตอบของ Willemoes (รหัส js ภายในตัวควบคุม) ในตัวอย่างนั้นคุณควรตรวจสอบใน HTML ว่าตัวแปร single_object เป็นโมฆะหรือไม่ได้กำหนด
Ena

2
{{(FooController.results | filter: {id: 1}) [0] .name}: true} - หากใครกำลังมองหาการจับคู่แบบตรงทั้งหมด
George Sharvadze

12

คุณสามารถใช้ng-repeatและเลือกข้อมูลได้ก็ต่อเมื่อข้อมูลตรงกับสิ่งที่คุณกำลังมองหาng-show เช่น:

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

2
หากอาร์เรย์ของคุณมีรายการมากกว่าจำนวนเล็กน้อยสิ่งนี้จะสร้างขอบเขตที่ไม่จำเป็นจำนวนมากซึ่งอาจทำให้แอปพลิเคชันของคุณช้าลง
The DIMM Reaper

9

คุณสามารถวนซ้ำอาร์เรย์ของคุณ:

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

หากคุณไม่ต้องการเขียนลูปที่ยุ่งเหยิงนี้คุณสามารถพิจารณาใช้underscore.jsหรือLo-Dash (ตัวอย่างในภายหลัง):

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

8

หากคุณต้องการรายการเช่นเมืองบนพื้นฐานของรหัสรัฐให้ใช้

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

7

น่าเสียดาย (เว้นแต่ฉันจะเข้าใจผิด) ฉันคิดว่าคุณต้องทำซ้ำบนวัตถุผลลัพธ์

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

อย่างน้อยวิธีนี้มันจะแยกออกจากการทำซ้ำทันทีที่พบรหัสการจับคู่ที่ถูกต้อง


ทำไม? คุณมีอะไรสำรองไหม?
simonlchilds

11
คุณรู้อะไรไหม .. ? ฉันเพียงแค่ออกไปอีกครั้งอ่าน Javascript - ชิ้นส่วนที่ดีที่จะตอบโต้ข้อโต้แย้งของคุณและฉันรู้สึกผิด! ตลอดเวลาที่ผ่านมาฉันทำผิด! มันไม่ได้ทำให้ฉันมีปัญหาใด ๆ แม้ว่า ... ฉันได้อัปเดตคำตอบแล้ว
simonlchilds

6

ทำไมสถานการณ์ซับซ้อน? นี่เป็นเรื่องง่ายที่จะเขียนบางฟังก์ชันดังนี้:

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

ใช้กรณี:

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

เอาท์พุท:

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>

เอาต์พุต: Azərbaycan


2

หากทำได้ให้ออกแบบโครงสร้างข้อมูล JSON โดยใช้ดัชนีอาร์เรย์เป็น ID คุณสามารถ "ทำให้ปกติ" อาร์เรย์ JSON ของคุณเป็นปกติได้ตราบเท่าที่คุณไม่มีปัญหาในการใช้ดัชนีอาร์เรย์เป็น "คีย์หลัก" และ "คีย์ต่างประเทศ" เช่น RDBMS ดังนั้นในอนาคตคุณสามารถทำสิ่งนี้ได้:

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

นี่เป็นวิธีการแก้"โดยการออกแบบ" สำหรับกรณีของคุณเพียง:

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

แน่นอนว่าหากรูปแบบ ID ของคุณเป็น"XX-0001"ซึ่งดัชนีอาร์เรย์เป็น0คุณสามารถจัดการสตริงเพื่อแมป ID ได้ มิฉะนั้นจะไม่มีอะไรสามารถทำได้ยกเว้นผ่านวิธีการวนซ้ำ


2

ฉันรู้ว่าฉันสายเกินไปที่จะตอบ แต่ก็ยังดีกว่าที่จะแสดงตัวแทนที่จะไม่แสดงเลย :) วิธีรับ ES6:

$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

วิธีง่ายๆในการรับ (หนึ่ง) องค์ประกอบจากอาร์เรย์โดย id:

วิธี find () ส่งคืนค่าขององค์ประกอบแรกในอาร์เรย์ที่ตรงตามฟังก์ชันการทดสอบที่ให้มา มิฉะนั้นจะส่งคืนที่ไม่ได้กำหนด

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

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

คุณไม่จำเป็นต้องใช้ตัวกรอง () และจับองค์ประกอบแรก xx.filter () [0] เหมือนในความคิดเห็นด้านบน

เหมือนกันสำหรับวัตถุในอาร์เรย์

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

แน่นอนถ้าคุณมีหลาย id ให้ใช้วิธี filter () เพื่อรับวัตถุทั้งหมด ไชโย

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

    });
});

ไม่แน่ใจว่ามันดีจริงหรือเปล่า แต่นี่เป็นประโยชน์สำหรับฉัน .. ฉันจำเป็นต้องใช้ $ scope เพื่อให้มันทำงานได้อย่างถูกต้อง


0

ใช้ $ timeout และเรียกใช้ฟังก์ชันเพื่อค้นหาในอาร์เรย์ "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

ฉันจะวนซ้ำอาร์เรย์ผลลัพธ์โดยใช้ตัวกรอง angularjs ดังนี้:

var foundResultObject = getObjectFromResultsList (ผลลัพธ์, 1);

function getObjectFromResultsList(results, resultIdToRetrieve) {
        return $filter('filter')(results, { id: resultIdToRetrieve }, true)[0];
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.