กรองคุณสมบัติของวัตถุตามคีย์ใน ES6


305

สมมติว่าฉันมีวัตถุ:

{
  item1: { key: 'sdfd', value:'sdfd' },
  item2: { key: 'sdfd', value:'sdfd' },
  item3: { key: 'sdfd', value:'sdfd' }
}

ฉันต้องการสร้างวัตถุอื่นโดยการกรองวัตถุด้านบนดังนั้นฉันจึงมีสิ่งที่ชอบ

 {
    item1: { key: 'sdfd', value:'sdfd' },
    item3: { key: 'sdfd', value:'sdfd' }
 }

ฉันกำลังมองหาวิธีที่สะอาดเพื่อทำสิ่งนี้ให้สำเร็จโดยใช้ Es6 ดังนั้นฉันจึงมีตัวดำเนินการกระจาย


ES6 ไม่มีตัวดำเนินการกระจายวัตถุและคุณไม่จำเป็นต้องใช้ที่นี่
Bergi

1
อาจซ้ำกันของJavaScript: filter () สำหรับ Objects
Jonathan H

@DanDascalescu แต่คำตอบนี้ให้วิธี ES6 ในการบรรลุสิ่งที่ OP ถามใช่หรือไม่?
Jonathan H

จะเป็นอย่างไรหากฉันต้องการกรองตามคีย์ / ค่า
jmchauv

คำตอบ:


584

หากคุณมีรายการค่าที่อนุญาตคุณสามารถเก็บไว้ในวัตถุได้อย่างง่ายดายโดยใช้:

const raw = {
  item1: { key: 'sdfd', value:'sdfd' },
  item2: { key: 'sdfd', value:'sdfd' },
  item3: { key: 'sdfd', value:'sdfd' }
};

const allowed = ['item1', 'item3'];

const filtered = Object.keys(raw)
  .filter(key => allowed.includes(key))
  .reduce((obj, key) => {
    obj[key] = raw[key];
    return obj;
  }, {});

console.log(filtered);

สิ่งนี้ใช้:

  1. Object.keysเพื่อแสดงรายการคุณสมบัติทั้งหมดในraw(ข้อมูลเดิม) จากนั้น
  2. Array.prototype.filter เพื่อเลือกคีย์ที่มีอยู่ในรายการที่อนุญาตโดยใช้
    1. Array.prototype.includes เพื่อให้แน่ใจว่ามีอยู่
  3. Array.prototype.reduce เพื่อสร้างวัตถุใหม่ที่มีคุณสมบัติที่อนุญาตเท่านั้น

สิ่งนี้จะสร้างสำเนาตื้นที่มีคุณสมบัติที่อนุญาต (แต่จะไม่คัดลอกคุณสมบัตินั้นเอง)

คุณยังสามารถใช้ตัวดำเนินการกระจายวัตถุเพื่อสร้างชุดของวัตถุโดยไม่ต้องกลายพันธุ์ (ขอบคุณrjerue ที่กล่าวถึงสิ่งนี้ ):

const raw = {
  item1: { key: 'sdfd', value:'sdfd' },
  item2: { key: 'sdfd', value:'sdfd' },
  item3: { key: 'sdfd', value:'sdfd' }
};

const allowed = ['item1', 'item3'];

const filtered = Object.keys(raw)
  .filter(key => allowed.includes(key))
  .reduce((obj, key) => {
    return {
      ...obj,
      [key]: raw[key]
    };
  }, {});

console.log(filtered);

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

const raw = {
  item1: { key: 'sdfd', value:'sdfd' },
  item2: { key: 'sdfd', value:'sdfd' },
  item3: { key: 'sdfd', value:'sdfd' }
};

const allowed = ['item1', 'item3'];

Object.keys(raw)
  .filter(key => !allowed.includes(key))
  .forEach(key => delete raw[key]);

console.log(raw);

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


1
ขอบคุณที่ทำงานได้ดี ฉันยังพบวิธีการโดยใช้ 'deconstruction syntax IE: const {item1, item3} = raw const newObject = {item1, item3}
29er

2
โครงสร้างจะใช้งานได้ (ใช้ได้ดี) แต่เป็นเวลารวบรวมเท่านั้น คุณไม่สามารถทำให้เป็นรายการคุณสมบัติแบบไดนามิกหรือระบุกฎที่ซับซ้อนใด ๆ (ลูปสามารถมีการเรียกกลับการตรวจสอบความถูกต้องแนบมาด้วย)
ssube

3
ฉันโหวตไม่พอ! ทำได้ดีมากสำหรับการใช้ตัวกรองและลดและไม่สร้างวัตถุอื่นจาก for loop และยอดเยี่ยมมากที่คุณแยกเวอร์ชันที่ไม่เปลี่ยนรูปและเปลี่ยนแปลงได้อย่างชัดเจน +1
Sukima

3
คำเตือนด่วน: Array.prototype.includesไม่ได้เป็นส่วนหนึ่งของ ES6 เปิดตัวใน ECMAScript 2016 (ES7)
Vineet

3
หากคุณต้องการลดขนาดด้วยวิธีที่ไม่เปลี่ยนรูปคุณสามารถแทนที่เนื้อหาฟังก์ชันด้วย return {... obj, [key]: raw [key]}
rjerue

101

หากคุณพอใจกับการใช้ไวยากรณ์ ES6 ฉันพบว่าวิธีที่สะอาดที่สุดในการทำสิ่งนี้ดังที่ระบุไว้ที่นี่และนี่คือ:

const data = {
  item1: { key: 'sdfd', value:'sdfd' },
  item2: { key: 'sdfd', value:'sdfd' },
  item3: { key: 'sdfd', value:'sdfd' }
};

const { item2, ...newData } = data;

ตอนนี้newDataประกอบด้วย:

{
  item1: { key: 'sdfd', value:'sdfd' },
  item3: { key: 'sdfd', value:'sdfd' }
};

หรือถ้าคุณมีคีย์ที่จัดเก็บเป็นสตริง:

const key = 'item2';
const { [key]: _, ...newData } = data;

ในกรณีหลัง[key]จะถูกแปลงเป็นitem2แต่เนื่องจากคุณกำลังใช้constงานคุณจึงต้องระบุชื่อสำหรับงานนั้น _แสดงถึงมูลค่าการทิ้ง

ให้เป็นปกติมากกว่านี้:

const { item2, ...newData } = data; // Assign item2 to item2
const { item2: someVarName, ...newData } = data; // Assign item2 to someVarName
const { item2: _, ...newData } = data; // Assign item2 to _
const { ['item2']: _, ...newData } = data; // Convert string to key first, ...

สิ่งนี้ไม่เพียงลดการทำงานของคุณให้เหลือเพียงซับเดียว แต่ยังไม่ต้องการให้คุณรู้ว่าคีย์อื่น ๆ คืออะไร (คีย์ที่คุณต้องการเก็บรักษา)


5
" _แสดงถึงมูลค่าทิ้ง" นี้มาจากไหน? ครั้งแรกที่ฉันเห็น
yhabib

6
ฉันเชื่อว่านี่เป็นอนุสัญญาที่นำมาใช้โดยชุมชน JS An _เป็นเพียงชื่อตัวแปรที่ถูกต้องซึ่งสามารถใช้ใน JS ได้ แต่เนื่องจากไม่มีชื่อค่อนข้างมากจึงไม่ควรใช้ในลักษณะนั้นหากคุณต้องการสื่อถึงเจตนา ดังนั้นจึงถูกนำมาใช้เพื่อแสดงตัวแปรที่คุณไม่สนใจ การอภิปรายเพิ่มเติมเกี่ยวกับเรื่องนี้: stackoverflow.com/questions/11406823/…
Ryan H.

2
นี้มาก tidier กว่าคำตอบที่ได้รับการยอมรับหลีกเลี่ยงค่าใช้จ่ายในการสร้างอาร์เรย์ใหม่ที่มี Object.keys () และค่าใช้จ่ายในการทำซ้ำอาร์เรย์ด้วยและfilter reduce
ericsoco

3
@yhabib _ไม่สำคัญมันเป็นแค่ชื่อตัวแปรคุณสามารถเปลี่ยนชื่อเป็นอะไรก็ได้ที่คุณต้องการ
วิค

1
@Gerrat ฉันไม่คิดว่าวิธีแก้ปัญหาทั่วไปจะเป็นเพียงซับเดียวที่ไม่สำคัญ สำหรับสิ่งนั้นฉันจะใช้omitฟังก์ชันของlodash : lodash.com/docs/4.17.10#omitหรือหนึ่งในโซลูชันอื่น ๆ ที่ให้ไว้ที่นี่
Ryan H.

49

วิธีที่สะอาดที่สุดคือการใช้Lodash # pick

const _ = require('lodash');

const allowed = ['item1', 'item3'];

const obj = {
  item1: { key: 'sdfd', value:'sdfd' },
  item2: { key: 'sdfd', value:'sdfd' },
  item3: { key: 'sdfd', value:'sdfd' }
}

const filteredObj = _.pick(obj, allowed)

3
สิ่งสำคัญคือต้องชี้ให้เห็นว่าจำเป็นต้องดาวน์โหลดการพึ่งพาโปรเจ็กต์เพิ่มเติมบนรันไทม์
S. Esteves

2
_.omit (obj, ["item2"]) - lodash.omit ตรงกันข้ามกับ lodash.pick
Alexander Solovyev

นอกจากนี้ยังมี ramda.pick ถ้าคุณใช้ Ramda! ramdajs.com/docs/#pick
Roman Scher

37

ไม่มีอะไรที่ไม่เคยพูดมาก่อน แต่จะรวมคำตอบบางคำเข้ากับคำตอบ ES6 ทั่วไป:

const raw = {
  item1: { key: 'sdfd', value: 'sdfd' },
  item2: { key: 'sdfd', value: 'sdfd' },
  item3: { key: 'sdfd', value: 'sdfd' }
};

const filteredKeys = ['item1', 'item3'];

const filtered = filteredKeys
  .reduce((obj, key) => ({ ...obj, [key]: raw[key] }), {});

console.log(filtered);


1
นี่เป็นวิธีแก้ปัญหาที่ง่ายและมีประสิทธิภาพมากกว่าวิธีอื่น ๆ )
pomeh

31

อีกวิธีหนึ่งใน Modern JS หนึ่งบรรทัดที่ไม่มีไลบรารีภายนอกไม่มีห้องสมุดภายนอก

ฉันกำลังเล่นกับคุณสมบัติ " ทำลายล้าง ":

const raw = {
    item1: { key: 'sdfd', value: 'sdfd' },
    item2: { key: 'sdfd', value: 'sdfd' },
    item3: { key: 'sdfd', value: 'sdfd' }
  };
var myNewRaw = (({ item1, item3}) => ({ item1, item3 }))(raw);
console.log(myNewRaw);


2
var myNewRaw = (({ item1, item3}) => ({ item1, item3 }))(raw);ปัญหาไวยากรณ์
Awol

1
มีสองสิ่งที่ย่ออยู่ที่นี่: สิ่งแรกก่อนมีการประกาศฟังก์ชัน เป็นฟังก์ชันลูกศร (ใช้วัตถุและส่งคืนวัตถุ) มันเหมือนกับฟังก์ชัน (obj) {return obj;} สิ่งที่สองคือ ES6 อนุญาตให้มีการทำลายล้างในอนาคต ในการประกาศฟังก์ชันของฉันฉันทำลายโครงสร้างวัตถุของฉัน {item1, item3} และสิ่งสุดท้ายคือฉันเรียกใช้ฟังก์ชันของตัวเอง คุณสามารถใช้ฟังก์ชันเรียกใช้ตัวเองเพื่อจัดการขอบเขตของคุณได้เช่น แต่นี่เป็นเพียงการย่อโค้ด ฉันหวังว่ามันจะชัดเจน ถ้าพลาดอะไรอย่าลังเลที่จะเพิ่มเติม
พ.ย.

6
นี่คือแนวทางสมัยใหม่ที่ต้องการ imho
mattdlockyer

1
คำตอบที่ได้รับการยอมรับจะมีกุญแจที่อยู่ในรายการตัวกรองและมีอยู่ในข้อมูลเดิม ฉันเชื่อว่าคำตอบของคุณจะแทรกคีย์ที่ขาดหายไปพร้อมกับundefinedค่าตัวอย่างเช่นหากไม่มีข้อมูลเดิมของitem3ฉันฉันคิดว่ารหัสของคุณจะเพิ่มเข้าไป อาจมีกรณีการใช้งานที่ไม่พึงปรารถนา (สำหรับกรณีการใช้งานของฉันมันใช้ได้ฉันกำลังใช้อยู่!)
AjahnCharles

1
@NikaKasradze โดยไม่มีวงเล็บฟังก์ชันจะส่งกลับไม่ได้กำหนด Awol ช่วยฉันในจุดนั้นในครั้งแรก และหลังจากอ่านบล็อกและอ่านข้อกำหนดแล้วฉันก็เข้าใจดีขึ้น จะพยายามอธิบายสั้น ๆ ในความคิดเห็นอื่นหากคุณไม่ทราบ
Novy

25

ตอนนี้คุณสามารถทำให้สั้นลงและง่ายขึ้นได้โดยใช้เมธอดObject.fromEntries (ตรวจสอบการรองรับเบราว์เซอร์):

const raw = { item1: { prop:'1' }, item2: { prop:'2' }, item3: { prop:'3' } };

const allowed = ['item1', 'item3'];

const filtered = Object.fromEntries(
   Object.entries(raw).filter(
      ([key, val])=>allowed.includes(key)
   )
);

อ่านเพิ่มเติมเกี่ยวกับ: Object.fromEntries


1
ตอนนี้เป็นวิธีที่ดีที่สุดที่ฉันคิด ใช้งานง่ายกว่าลดมาก
Damon

10

คุณสามารถเพิ่ม generic ofilter(ใช้งานร่วมกับ generic oreduce) เพื่อให้คุณสามารถกรองออบเจ็กต์ได้อย่างง่ายดายเช่นเดียวกับอาร์เรย์ -

const oreduce = (f, acc, o) =>
  Object
    .entries (o)
    .reduce
      ( (acc, [ k, v ]) => f (acc, v, k, o)
      , acc
      )

const ofilter = (f, o) =>
  oreduce
    ( (acc, v, k, o)=>
        f (v, k, o)
          ? Object.assign (acc, {[k]: v})
          : acc
    , {}
    , o
    )

เราสามารถเห็นมันทำงานได้ที่นี่ -

const data =
  { item1: { key: 'a', value: 1 }
  , item2: { key: 'b', value: 2 }
  , item3: { key: 'c', value: 3 }
  }

console.log
  ( ofilter
      ( (v, k) => k !== 'item2'
      , data
      )
      // [ { item1: { key: 'a', value: 1 } }
      // , { item3: { key: 'c', value: 3 } }
      // ]

  , ofilter
      ( x => x.value === 3
      , data
      )
      // [ { item3: { key: 'c', value: 3 } } ]
  )

ตรวจสอบผลลัพธ์ในเบราว์เซอร์ของคุณเองด้านล่าง -

ฟังก์ชันทั้งสองนี้สามารถใช้งานได้หลายวิธี ฉันเลือกที่จะแนบเข้าไปArray.prototype.reduceข้างในoreduceแต่คุณสามารถเขียนทั้งหมดตั้งแต่เริ่มต้นได้อย่างง่ายดาย


ผมชอบวิธีการแก้ปัญหาของคุณ แต่ฉันไม่ทราบวิธีการที่ชัดเจนมากขึ้น / มีประสิทธิภาพมากขึ้นเมื่อเทียบกับคนนี้
Jonathan H

3
นี่คือเกณฑ์มาตรฐานที่แสดงว่าโซลูชันของคุณเร็วที่สุด
Jonathan H

ในoreduceครั้งแรกaccเป็นเงาใน.reduce(acc, k)และในเงา - เรียกว่ามีตัวแปรที่เรียกว่าเป็นอย่างดี - ซึ่งเป็นที่? ofilterooreduceo
Jarrod Mosen

ในofilterตัวแปรoจะถูกแรเงา แต่จะชี้ไปที่ตัวแปรอินพุตเดียวกันเสมอ นั่นเป็นเหตุผลว่าทำไมมันถึงถูกเงาที่นี่เพราะมันเหมือนกัน - ตัวสะสม ( acc) ก็ถูกเงาด้วยเพราะมันแสดงให้เห็นชัดเจนขึ้นว่าข้อมูลเคลื่อนที่ผ่านแลมด้าอย่างไร accไม่ได้มีผลผูกพันแบบเดียวกันเสมอไปแต่แสดงถึงสถานะถาวรในปัจจุบันของผลการคำนวณที่เราต้องการส่งคืน
ขอบคุณ

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

9

โอเคซับเดียวนี่ยังไง

    const raw = {
      item1: { key: 'sdfd', value: 'sdfd' },
      item2: { key: 'sdfd', value: 'sdfd' },
      item3: { key: 'sdfd', value: 'sdfd' }
    };

    const filteredKeys = ['item1', 'item3'];

    const filtered = Object.assign({}, ...filteredKeys.map(key=> ({[key]:raw[key]})));

2
ทางออกที่น่าทึ่งที่สุดของคำตอบทั้งหมด +1
GergőHorváth

จะเป็นอย่างไรถ้าคุณรู้เฉพาะคีย์ที่ต้องการลบ ... ไม่ใช่คีย์ที่คุณต้องการเก็บ?
Jason

7

นี่คือวิธีที่ฉันทำเมื่อเร็ว ๆ นี้:

const dummyObj = Object.assign({}, obj);
delete dummyObj[key];
const target = Object.assign({}, {...dummyObj});

หืม ดูเหมือนว่าคุณกำลังผสมไวยากรณ์แบบเก่าและแบบใหม่ Object.assign == ...คุณสามารถเขียนconst dummyObj = { ...obj }และconst target = { ...dummyObj }. นอกจากนี้สิ่งหลังไม่จำเป็นเลยเนื่องจากคุณสามารถทำงานกับ dummyObj ได้โดยตรงในภายหลัง
Andy

6

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

const data = {
  allowed1: 'blah',
  allowed2: 'blah blah',
  notAllowed: 'woah',
  superSensitiveInfo: 'whooooah',
  allowed3: 'bleh'
};

const whitelist = ['allowed1', 'allowed2', 'allowed3'];

function sanitize(data, whitelist) {
    return whitelist.reduce(
      (result, key) =>
        data[key] !== undefined
          ? Object.assign(result, { [key]: data[key] })
          : result,
      {}
    );
  }

  sanitize(data, whitelist)

5

Piggybacking ในคำตอบของ ssube answeranswer

นี่คือเวอร์ชันที่ใช้ซ้ำได้

Object.filterByKey = function (obj, predicate) {
  return Object.keys(obj)
    .filter(key => predicate(key))
    .reduce((out, key) => {
      out[key] = obj[key];
      return out;
    }, {});
}

เพื่อเรียกว่าใช้

const raw = {
  item1: { key: 'sdfd', value:'sdfd' },
  item2: { key: 'sdfd', value:'sdfd' },
  item3: { key: 'sdfd', value:'sdfd' }
};

const allowed = ['item1', 'item3'];

var filtered = Object.filterByKey(raw, key => 
  return allowed.includes(key));
});

console.log(filtered);

สิ่งที่สวยงามเกี่ยวกับฟังก์ชันลูกศร ES6 คือคุณไม่จำเป็นต้องส่งผ่านallowedเป็นพารามิเตอร์


5

วิธีแก้ปัญหาที่ง่ายกว่าโดยไม่ต้องใช้filterสามารถทำได้โดยObject.entries()ใช้แทนObject.keys()

const raw = {
  item1: { key: 'sdfd', value:'sdfd' },
  item2: { key: 'sdfd', value:'sdfd' },
  item3: { key: 'sdfd', value:'sdfd' }
};

const allowed = ['item1', 'item3'];

const filtered = Object.entries(raw).reduce((acc,elm)=>{
  const [k,v] = elm
  if (allowed.includes(k)) {
    acc[k] = v 
  }
  return acc
},{})

5

วิธีแก้ปัญหาอื่นโดยใช้วิธีการ "ใหม่" Array.reduce:

const raw = {
  item1: { key: 'sdfd', value:'sdfd' },
  item2: { key: 'sdfd', value:'sdfd' },
  item3: { key: 'sdfd', value:'sdfd' }
};

const allowed = ['item1', 'item3'];

const filtered = allowed.reduce((obj, key) => { 
  obj[key] = raw[key]; 
  return obj 
}, {})

console.log(filtered);

การสาธิตในซอนี้ ...


แต่ฉันชอบวิธีแก้ปัญหาในคำตอบนี้ที่นี่ซึ่งใช้และ:Object.fromEntries Array.filterArray.includes

const object = Object.fromEntries(
  Object.entries(raw).filter(([key, value]) => allowed.includes(key))
);

การสาธิตในซอนี้ ...


ร่วงโรยแนวทางที่สองของคุณซ้ำกับคำตอบนี้ที่ให้ไว้เมื่อปีที่แล้ว: stackoverflow.com/a/56081419/5522000
Art Schmidt

@ArtSchmidt ขอบคุณสำหรับความคิดเห็นของคุณ: พลาดอันนั้นในรายการยาว ๆ ฉันจะอ้างถึงคำตอบนั้นแทน
เหี่ยว

4

คุณสามารถทำสิ่งนี้:

const base = {
  item1: { key: 'sdfd', value:'sdfd' },
  item2: { key: 'sdfd', value:'sdfd' },
  item3: { key: 'sdfd', value:'sdfd' }
};

const filtered = (
    source => { 
        with(source){ 
            return {item1, item3} 
        } 
    }
)(base);

// one line
const filtered = (source => { with(source){ return {item1, item3} } })(base);

วิธีนี้ใช้ได้ผล แต่ไม่ชัดเจนและwithไม่แนะนำให้ใช้คำสั่ง ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with )


4

วิธีง่ายๆ! เพื่อทำสิ่งนี้.

const myData = {
  item1: { key: 'sdfd', value:'sdfd' },
  item2: { key: 'sdfd', value:'sdfd' },
  item3: { key: 'sdfd', value:'sdfd' }
};
const{item1,item3}=myData
const result =({item1,item3})


คุณไม่ได้กรองอะไรที่นี่เพียงแค่ทำลายข้อมูลที่ได้รับ แต่จะเกิดอะไรขึ้นเมื่อข้อมูลเปลี่ยนไป?
Idris Dopico Peña

@ IdrisDopicoPeña - การทำลายโครงสร้างคือตัวกรอง ออบเจ็กต์ของชื่อฟิลด์แตกต่างจากการใช้อาร์เรย์ของชื่อฟิลด์อย่างไร (แม้ว่าโซลูชันนี้จะเพิ่มคีย์ที่หายไป)
AjahnCharles

3

มีหลายวิธีที่จะทำให้สำเร็จ คำตอบที่ได้รับการยอมรับใช้คีย์กรองลดวิธีการซึ่งไม่ได้เป็น performant มากที่สุด

แทนที่จะใช้การfor...inวนซ้ำเพื่อวนซ้ำคีย์ของออบเจ็กต์หรือการวนลูปผ่านคีย์ที่อนุญาตจากนั้นการเขียนอ็อบเจ็กต์ใหม่จะมีประสิทธิภาพมากกว่า . 50%

const obj = {
  item1: { key: 'sdfd', value:'sdfd' },
  item2: { key: 'sdfd', value:'sdfd' },
  item3: { key: 'sdfd', value:'sdfd' }
};

const keys = ['item1', 'item3'];

function keysReduce (obj, keys) {
  return keys.reduce((acc, key) => {
    if(obj[key] !== undefined) {
      acc[key] = obj[key];
    }
    return acc;
  }, {});
};

function forInCompose (obj, keys) {
  const returnObj = {};
  for (const key in obj) {
    if(keys.includes(key)) {
      returnObj[key] = obj[key]
    }
  };
  return returnObj;
};

keysReduce(obj, keys);   // Faster if the list of allowed keys are short
forInCompose(obj, keys); // Faster if the number of object properties are low

ก. ดูjsPerfสำหรับเกณฑ์มาตรฐานของกรณีการใช้งานอย่างง่าย ผลลัพธ์จะแตกต่างกันไปตามเบราว์เซอร์


3
const filteredObject = Object.fromEntries(Object.entries(originalObject).filter(([key, value]) => key !== uuid))

2
มีคำตอบอื่น ๆ ที่ให้คำถามของ OP และมีการโพสต์เมื่อไม่นานมานี้ เมื่อโพสต์คำตอบโปรดตรวจสอบให้แน่ใจว่าคุณได้เพิ่มโซลูชันใหม่หรือคำอธิบายที่ดีขึ้นมากโดยเฉพาะเมื่อตอบคำถามเก่า ๆ
help-info.de

2

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

const unfilteredObj = {a: ..., b:..., c:..., x:..., y:...}

const filterObject = ({a,b,c}) => ({a,b,c})
const filteredObject = filterObject(unfilteredObject)

หรือถ้าคุณต้องการซับที่สกปรก:

const unfilteredObj = {a: ..., b:..., c:..., x:..., y:...}

const filteredObject = (({a,b,c})=>({a,b,c}))(unfilteredObject);

วิธีนี้จะเพิ่มคีย์ที่ไม่มีอยู่ในอาร์เรย์เดิม อาจเป็นปัญหาหรือไม่อย่างน้อยก็ควรชี้ให้เห็น
ponchietto

ฉันคิดว่าผู้ชายคนนี้แนะนำแล้ว: stackoverflow.com/a/49340650/2957169
AjahnCharles

2

คุณสามารถลบคุณสมบัติ spesific บนวัตถุของคุณ

items={
  item1: { key: 'sdfd', value:'sdfd' },
  item2: { key: 'sdfd', value:'sdfd' },
  item3: { key: 'sdfd', value:'sdfd' }
}

// Example 1
var key = "item2";
delete items[key]; 

// Example 2
delete items["item2"];

// Example 3
delete items.item2;

1

ตกลง,อย่างไร:

const myData = {
  item1: { key: 'sdfd', value:'sdfd' },
  item2: { key: 'sdfd', value:'sdfd' },
  item3: { key: 'sdfd', value:'sdfd' }
};

function filteredObject(obj, filter) {
  if(!Array.isArray(filter)) {
   filter = [filter.toString()];
  }
  const newObj = {};
  for(i in obj) {
    if(!filter.includes(i)) {
      newObj[i] = obj[i];
    }
  }
  return newObj;
}

และเรียกแบบนี้ว่า

filteredObject(myData, ['item2']); //{item1: { key: 'sdfd', value:'sdfd' }, item3: { key: 'sdfd', value:'sdfd' }}

1

ฟังก์ชันนี้จะกรองออบเจ็กต์ตามรายการคีย์ซึ่งมีประสิทธิภาพมากกว่าคำตอบก่อนหน้าเนื่องจากไม่ต้องใช้ Array.filter ก่อนเรียกลด ดังนั้น O (n) ของมันจึงตรงข้ามกับ O (n + ที่กรองแล้ว)

function filterObjectByKeys (object, keys) {
  return Object.keys(object).reduce((accum, key) => {
    if (keys.includes(key)) {
      return { ...accum, [key]: object[key] }
    } else {
      return accum
    }
  }, {})
}

1

ในระหว่างการวนซ้ำไม่ต้องคืนค่าใด ๆ เมื่อพบคุณสมบัติ / คีย์บางอย่างและดำเนินการต่อกับส่วนที่เหลือ:

const loop = product =>
Object.keys(product).map(key => {
    if (key === "_id" || key === "__v") {
        return; 
    }
    return (
        <ul className="list-group">
            <li>
                {product[key]}
                <span>
                    {key}
                </span>
            </li>
        </ul>
    );
});

1

อีกวิธีสั้น ๆ

function filterByKey(v,keys){
  const newObj ={};
  keys.forEach(key=>{v[key]?newObj[key]=v[key]:''});
  return newObj;
}

//given
let obj ={ foo: "bar", baz: 42,baz2:"blabla" , "spider":"man", monkey:true};

//when
let outObj =filterByKey(obj,["bar","baz2","monkey"]);

//then 
console.log(outObj);
  //{
  //  "baz2": "blabla",
  //  "monkey": true
  //}


0

อีกวิธีหนึ่งที่จะใช้Array.prototype.forEach()เป็น

const raw = {
  item1: {
    key: 'sdfd',
    value: 'sdfd'
  },
  item2: {
    key: 'sdfd',
    value: 'sdfd'
  },
  item3: {
    key: 'sdfd',
    value: 'sdfd'
  }
};

const allowed = ['item1', 'item3', 'lll'];

var finalObj = {};
allowed.forEach(allowedVal => {
  if (raw[allowedVal])
    finalObj[allowedVal] = raw[allowedVal]
})
console.log(finalObj)

ประกอบด้วยค่าเฉพาะคีย์ที่มีอยู่ในข้อมูลดิบและป้องกันการเพิ่มข้อมูลขยะ


0

นั่นจะเป็นทางออกของฉัน:

const filterObject = (obj, condition) => {
    const filteredObj = {};
    Object.keys(obj).map(key => {
      if (condition(key)) {
        dataFiltered[key] = obj[key];
      }
    });
  return filteredObj;
}

0

ฉันรู้ว่าสิ่งนี้มีคำตอบมากมายอยู่แล้วและเป็นคำถามที่ค่อนข้างเก่า แต่ฉันเพิ่งมากับซับเดียวที่เรียบร้อยนี้:

JSON.parse(JSON.stringify(raw, ['key', 'value', 'item1', 'item3']))

ซึ่งส่งคืนวัตถุอื่นที่มีเพียงแอตทริบิวต์ที่อนุญาตพิเศษ โปรดทราบว่าkeyและvalueรวมอยู่ในรายการ

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