จะหาค่าในอาร์เรย์ของวัตถุใน JavaScript ได้อย่างไร?


91

ฉันมีอาร์เรย์ของวัตถุ:

Object = {
   1 : { name : bob , dinner : pizza },
   2 : { name : john , dinner : sushi },
   3 : { name : larry, dinner : hummus }
}

ฉันต้องการค้นหาออบเจ็กต์ / อาร์เรย์ที่คีย์คือ "อาหารเย็น" และดูว่าตรงกับ "ซูชิ" หรือไม่

ฉันรู้ว่า jQuery มี $ .inArray แต่ดูเหมือนจะใช้ไม่ได้กับอาร์เรย์ของวัตถุ หรือบางทีฉันคิดผิด indexOf ดูเหมือนว่าจะทำงานในระดับอาร์เรย์เดียวเท่านั้น

ไม่มีฟังก์ชันหรือรหัสที่มีอยู่สำหรับสิ่งนี้หรือไม่?


นี่เคยถามมาก่อน คุณต้องเขียนฟังก์ชันของคุณเองหรือใช้ไลบรารีอื่น
Felix Kling

1
โปรดทราบว่าObjectสงวนไว้ใน Javascript Objectเป็นวัตถุวัตถุเช่นแม่ของวัตถุทั้งหมด
อาดัมส์

1
คำถามและคำตอบที่ยอมรับไม่เกี่ยวข้องกับอาร์เรย์หลายมิติ แต่มีมากกว่าการกรองอาร์เรย์ 1 มิติตามค่าคุณสมบัติของรายการ => พวกเขาไม่ได้แก้ปัญหาของฉัน "การค้นหาค่าในอาร์เรย์หลายมิติ"
Martin Schneider

คำตอบ:


213

หากคุณมีอาร์เรย์เช่น

var people = [
  { "name": "bob", "dinner": "pizza" },
  { "name": "john", "dinner": "sushi" },
  { "name": "larry", "dinner": "hummus" }
];

คุณสามารถใช้filterวิธีการของวัตถุ Array:

people.filter(function (person) { return person.dinner == "sushi" });
  // => [{ "name": "john", "dinner": "sushi" }]

ในการใช้งาน JavaScript รุ่นใหม่คุณสามารถใช้นิพจน์ฟังก์ชัน:

people.filter(p => p.dinner == "sushi")
  // => [{ "name": "john", "dinner": "sushi" }]

คุณสามารถค้นหาผู้ที่"dinner": "sushi"ใช้ไฟล์map

people.map(function (person) {
  if (person.dinner == "sushi") {
    return person
  } else {
    return null
  }
}); // => [null, { "name": "john", "dinner": "sushi" }, null]

หรือก reduce

people.reduce(function (sushiPeople, person) {
  if (person.dinner == "sushi") {
    return sushiPeople.concat(person);
  } else {
    return sushiPeople
  }
}, []); // => [{ "name": "john", "dinner": "sushi" }]

ฉันแน่ใจว่าคุณสามารถสรุปสิ่งนี้ให้กับคีย์และค่าโดยพลการได้!


7
โปรดทราบว่าโซลูชันเหล่านี้เป็นส่วนหนึ่งของ ECMAScript 5 และไม่รองรับใน IE8 kangax.github.com/es5-compat-table เท่าที่ฉันชอบคำตอบของ @ adamse alex เป็น "เบราว์เซอร์เก่า ๆ " ที่เป็นมิตรมากกว่า ไม่แน่ใจเกี่ยวกับประสิทธิภาพแม้ว่า
EasyCo

@SalmanA - หรือคำถามหรือวิธีแก้ปัญหานั้นอ้างถึง jQuery ใช้ตัวกรอง javascript () ไม่ใช่ jQuery เฉพาะ $ .filter () - tutorialspoint.com/javascript/array_filter.htm
Tapirboy

ตามที่ EasyCo กล่าวไว้ฟังก์ชันตัวกรองไม่รองรับใน IE8 อย่างไรก็ตามสามารถเพิ่มลงในต้นแบบ Array ได้อย่างง่ายดายดังนั้นจึงสามารถใช้งานได้ในเบราว์เซอร์ใด ๆ ที่มีฟังก์ชั่นเล็ก ๆ ที่จุดเริ่มต้นของสคริปต์ของคุณ นี่คือที่ที่ระบุไว้ในเอกสารกรอง มันให้ฟังก์ชันที่แน่นอนที่ระบุไว้ใน ECMA-262 ดังนั้นจึงเป็นสิ่งเดียวกันอย่างแท้จริง
dallin

1
ฉันเพิ่งเพิ่มคำตอบซึ่งใช้grepวิธีของ jQuery อาจเหมาะสมที่จะตอบคำถามของคุณเป็นแนวคิดเดียวกับสิ่งที่คุณกำลังทำอยู่ แต่ jQuery ขึ้นอยู่กับเบราว์เซอร์และเป็นมิตรกับเบราว์เซอร์
Zach Lysobey

มีเหตุผลที่ฉันยังคงได้รับข้อผิดพลาดอ้างอิงกับตัวแปรส่งคืนของฉันหรือไม่ ฉันลองคำตอบสองอันดับแรกที่ส่งกลับ "x '' และมันก็บอกว่ามันไม่ได้กำหนด ...
Evan Lalo

18

jQuery มีเมธอดในตัวjQuery.grepที่ทำงานคล้ายกับfilterฟังก์ชันES5 จากคำตอบของ @ adamseและควรทำงานได้ดีกับเบราว์เซอร์รุ่นเก่า

โดยใช้ตัวอย่างของ Adamse:

var peoples = [
  { "name": "bob", "dinner": "pizza" },
  { "name": "john", "dinner": "sushi" },
  { "name": "larry", "dinner": "hummus" }
];

คุณสามารถทำสิ่งต่อไปนี้ได้

jQuery.grep(peoples, function (person) { return person.dinner == "sushi" });
  // => [{ "name": "john", "dinner": "sushi" }]

10
var getKeyByDinner = function(obj, dinner) {
    var returnKey = -1;

    $.each(obj, function(key, info) {
        if (info.dinner == dinner) {
           returnKey = key;
           return false; 
        };   
    });

    return returnKey;       

}

jsFiddlejsFiddle

ตราบใดที่-1ยังไม่มีคีย์ที่ถูกต้อง


เกือบจะโหวตให้คะแนนนี้ แต่ไม่มีคำอธิบายในโพสต์
mickmackusa

10

หากคุณจะทำการค้นหาบ่อยๆลองพิจารณาเปลี่ยนรูปแบบของวัตถุของคุณเพื่อให้อาหารเย็นเป็นกุญแจสำคัญ ซึ่งเหมือนกับการกำหนดคีย์คลัสเตอร์หลักในตารางฐานข้อมูล ตัวอย่างเช่น:

Obj = { 'pizza' : { 'name' : 'bob' }, 'sushi' : { 'name' : 'john' } }

ตอนนี้คุณสามารถเข้าถึงได้อย่างง่ายดายดังนี้: Object['sushi']['name']

หรือถ้าวัตถุนั้นเรียบง่ายจริงๆ (มีแค่ 'ชื่อ' ในออบเจ็กต์) คุณก็สามารถเปลี่ยนเป็น:

Obj = { 'pizza' : 'bob', 'sushi' : 'john' }

แล้วเข้าถึงมันเช่น: Object['sushi'].

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


1
รักคุณตอบ แต่ฉันพบปัญหาเกี่ยวกับไวยากรณ์: ของฉันใช้ได้เฉพาะแบบนี้ obj = {"pizza": {"name": "bob"}, "sushi": {"name": "john"}} alert ( obj ['pizza'] ['name']); แต่ยังคง. ขอบคุณ! พบสิ่งที่ฉันกำลังค้นหา! )
aleXela

@alexela ขอบคุณ alexela! ฉันอัปเดตคำตอบของฉันด้วยการสังเกตที่ชาญฉลาดของคุณ! ฉันเพิ่งคัดลอกตัวอย่างในโพสต์ของ OP และละเลยที่จะเพิ่มเครื่องหมายคำพูด แต่คุณพูดถูก - มันจะไม่ได้ผลเว้นแต่จะมีเครื่องหมายคำพูดอย่างน้อยรอบค่า (สมมติว่าเป็นค่าไม่ใช่ตัวแปร)
dallin

3

คุณสามารถค้นหาวัตถุในอาร์เรย์ด้วยไลบรารีAlasql :

var data = [ { name : "bob" , dinner : "pizza" }, { name : "john" , dinner : "sushi" },
     { name : "larry", dinner : "hummus" } ];

var res = alasql('SELECT * FROM ? WHERE dinner="sushi"',[data]);

ลองตัวอย่างนี้ใน jsFiddle


3
ฉันไม่แน่ใจว่านี่สมควรถูกโหวตจริงๆ Sql เช่นเคียวรีในคอลเลกชันกลายเป็นเหตุผลและเขียนได้ง่ายกว่ามากเมื่อข้อกำหนดซับซ้อนกว่าตัวกรองเดียวหรือลดการโทร Alasql เป็นห้องสมุดที่ค่อนข้างน่าประทับใจ แต่เป็นที่ยอมรับกันมากเกินไปสำหรับตัวอย่างข้างต้น
TomDotTom

1
หากวัตถุนั้นมาจากแหล่งที่มาของ SQL คำตอบนี้ก็คืออัจฉริยะอย่างแท้จริง
edwardsmarkf

1

คุณสามารถใช้วิธีง่ายๆในการวนซ้ำ:

for (prop in Obj){
    if (Obj[prop]['dinner'] === 'sushi'){

        // Do stuff with found object. E.g. put it into an array:
        arrFoo.push(Obj[prop]);
    }
}

ตัวอย่างซอต่อไปนี้ใส่วัตถุทั้งหมดที่มีdinner:sushiในอาร์เรย์:

https://jsfiddle.net/3asvkLn6/1/


1

มีคำตอบที่ดีมากมายที่นี่แล้วทำไมไม่ลองใช้ไลบรารีเช่น lodash หรือขีดล่าง :)

obj = {
   1 : { name : 'bob' , dinner : 'pizza' },
   2 : { name : 'john' , dinner : 'sushi' },
   3 : { name : 'larry', dinner : 'hummus' }
}

_.where(obj, {dinner: 'pizza'})
>> [{"name":"bob","dinner":"pizza"}]

0

ฉันต้องค้นหาโครงสร้างแผนผังเว็บไซต์ที่ซ้อนกันสำหรับรายการใบไม้แรกที่ปรับเปลี่ยนเส้นทางที่กำหนด ฉันคิดรหัสต่อไปนี้โดยใช้.map() .filter()และ.reduce. /cผลตอบแทนที่รายการสุดท้ายที่พบว่าตรงกับเส้นทาง

var sitemap = {
  nodes: [
    {
      items: [{ path: "/a" }, { path: "/b" }]
    },
    {
      items: [{ path: "/c" }, { path: "/d" }]
    },
    {
      items: [{ path: "/c" }, { path: "/d" }]
    }
  ]
};

const item = sitemap.nodes
  .map(n => n.items.filter(i => i.path === "/c"))
  .reduce((last, now) => last.concat(now))
  .reduce((last, now) => now);

แก้ไข 4n4904z07


0

หากคุณต้องการค้นหาวัตถุเฉพาะผ่านฟังก์ชันการค้นหาให้ลองทำสิ่งนี้:

    function findArray(value){

        let countLayer = dataLayer.length;
        for(var x = 0 ; x < countLayer ; x++){

            if(dataLayer[x].user){
                let newArr = dataLayer[x].user;
                let data = newArr[value];
                return data;
            }

        }

        return null;

    }

    findArray("id");

นี่คือวัตถุตัวอย่าง:

layerObj = {
    0: { gtm.start :1232542, event: "gtm.js"},
    1: { event: "gtm.dom", gtm.uniqueEventId: 52},
    2: { visitor id: "abcdef2345"},
    3: { user: { id: "29857239", verified: "Null", user_profile: "Personal", billing_subscription: "True", partners_user: "adobe"}
}

โค้ดจะวนซ้ำและค้นหาอาร์เรย์ "ผู้ใช้" และจะค้นหาวัตถุที่คุณต้องการภายใน

ปัญหาของฉันคือเมื่อดัชนีอาร์เรย์เปลี่ยนทุกการรีเฟรชหน้าต่างและอยู่ในอาร์เรย์ที่ 3 หรือที่สอง แต่ก็ไม่สำคัญ

ทำงานอย่างมีเสน่ห์สำหรับฉัน!

ในตัวอย่างของคุณสั้นกว่าเล็กน้อย:

function findArray(value){

    let countLayer = Object.length;
    for(var x = 0 ; x < countLayer ; x++){

        if(Object[x].dinner === value){
            return Object[x];
        }

    }

    return null;

}

findArray('sushi');

0

เราใช้การสแกนวัตถุสำหรับการประมวลผลข้อมูลส่วนใหญ่ของเรา เป็นแนวคิดที่เรียบง่ายมาก แต่ช่วยให้มีสิ่งดีๆมากมาย นี่คือวิธีแก้ปัญหาของคุณ

// const objectScan = require('object-scan');

const findDinner = (dinner, data) => objectScan(['*'], {
  abort: true,
  rtn: 'value',
  filterFn: ({ value }) => value.dinner === dinner
})(data);

const data = {
  1: { name: 'bob', dinner: 'pizza' },
  2: { name: 'john', dinner: 'sushi' },
  3: { name: 'larry', dinner: 'hummus' }
};

console.log(findDinner('sushi', data));
// => { name: 'john', dinner: 'sushi' }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan@13.7.1"></script>

Disclaimer : ฉันเป็นผู้เขียนการสแกนวัตถุ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.