ลบคุณสมบัติสำหรับวัตถุทั้งหมดในอาร์เรย์


117

ฉันต้องการลบbadคุณสมบัติออกจากทุกออบเจ็กต์ในอาร์เรย์ มีวิธีที่ดีกว่าการใช้การforวนซ้ำและลบออกจากทุกวัตถุหรือไม่?

var array = [{"bad": "something", "good":"something"},{"bad":"something", "good":"something"},...];

for (var i = 0, len = array.length; i < len; i++) {
  delete array[i].bad;
}

ดูเหมือนว่าน่าจะมีวิธีใช้prototypeหรือบางอย่าง ฉันไม่รู้ ไอเดีย?


1
ไม่สำคัญวิธีอื่น ๆ ไม่สามารถรับ O (n) เชิงเส้นน้อยกว่านั้นได้ ไม่ว่าคุณจะใช้อะไรก็ตามคุณจะต้องเข้าถึงองค์ประกอบอาร์เรย์ทั้งหมดของคุณ
Brian

ต้นแบบ? จะช่วยได้อย่างไร? หรืออินสแตนซ์อ็อบเจ็กต์เหล่านั้นทั้งหมดเป็นคอนสตรัคเตอร์เดียวกันและแชร์ค่าร่วมกันสำหรับbad?
Bergi

1
@Bergi ฉันสงสัยว่าพวกเขาอ้างถึง PrototypeJS หรือArrayPrototype ซึ่ง dystroy ยกตัวอย่าง
เอียน

ฉันไม่แน่ใจว่าคุณควรเก็บ array.length ไว้ในตัวแปรก่อนที่จะวนลูป ฉันแน่ใจว่าคุณจะเห็นว่ามันไม่คุ้มกับความเจ็บปวดถ้าคุณทำโปรไฟล์
Denys Séguret

1
@ZackArgyle ใช่ในกรณีทั่วไปไม่มีอะไรเร็วกว่านี้
Denys Séguret

คำตอบ:


125

วิธีเดียวคือเครื่องสำอางและในความเป็นจริงลูป

ตัวอย่างเช่น :

array.forEach(function(v){ delete v.bad });

หมายเหตุ:

  • ถ้าคุณต้องการที่จะเข้ากันได้กับ IE8, คุณจะต้องชิมสำหรับ forEach ตามที่คุณกล่าวถึงต้นแบบ prototype.js ก็มี shimเช่นกัน
  • deleteเป็นหนึ่งในที่เลวร้ายที่สุด"ฆาตกรต่อการเพิ่มประสิทธิภาพ" การใช้แอปพลิเคชันของคุณมักจะทำลายประสิทธิภาพ คุณไม่สามารถหลีกเลี่ยงได้หากคุณต้องการลบคุณสมบัติจริงๆ แต่คุณสามารถตั้งค่าคุณสมบัติเป็นundefinedหรือเพียงแค่สร้างวัตถุใหม่โดยไม่มีคุณสมบัติ

1
ไม่ดีไปกว่าลูปมากนักหากลูปได้รับอนุญาตให้เป็น "ของปลอม" - มีเส้นเดียวด้วย: Pfor(var i = 0; i < array.length ) delete array[i].bad
Esailija

1
@Esailija ขึ้นอยู่. ฉันชอบใช้forEachเพราะฉันพบว่าโค้ดมีความชัดเจนมากขึ้น (และเพราะฉันเลิกกังวลเกี่ยวกับ IE มานานแล้ว)
Denys Séguret

1
ทั้งสองรายการไม่ได้แสดง "ลบคุณสมบัติที่ไม่ดีของวัตถุทั้งหมดในอาร์เรย์นี้" ด้วยวิธีที่แตกต่างกันอย่างสิ้นเชิง forEachมีความหมายทั่วไปและไม่มีความหมายในตัวมันเองเหมือนforวนซ้ำ
Esailija

1
@Esailija ฉันเห็นด้วย นั่นเป็นเหตุผลว่าทำไมฉันถึงยกย่องให้เป็น "เครื่องสำอาง" ไม่ชัดเจนในคำตอบของฉัน?
Denys Séguret

โชคร้าย. ฉันจะติดกับ for loop ซึ่งโดยทั่วไปเร็วกว่า forEach และจริงๆ ... ใครสนใจ IE8 ขอบคุณสำหรับความช่วยเหลือ
Zack Argyle

185

ด้วย ES6 คุณสามารถแยกโครงสร้างแต่ละวัตถุเพื่อสร้างใหม่โดยไม่มีแอตทริบิวต์ที่ตั้งชื่อ

const newArray = array.map(({dropAttr1, dropAttr2, ...keepAttrs}) => keepAttrs)

17
การนำไปใช้กับปัญหาเบื้องต้นอาจเป็นconst newArray = array.map(({ bad, ...item }) => item);
dhilt

1
ขอแนะนำอย่างยิ่งเนื่องจากไม่ได้ปรับเปลี่ยนอาร์เรย์เดิม (การดำเนินการที่ไม่เปลี่ยนรูป)
Pizzicato

1
นี่ควรเป็นคำตอบที่ยอมรับเพราะส่งคืนอาร์เรย์ใหม่แทนที่จะเขียนทับอาร์เรย์ที่มีอยู่
user1275105

คำตอบที่ดี แต่ใช้ไม่ได้หากชื่อคุณสมบัติมีจุด (.) เช่น 'bad.prop'
Yayati

@Amiraslan ฉันจะใช้// eslint-disable-next-line no-unused-vars
piotr_cz

21

ฉันชอบใช้แผนที่เพื่อลบคุณสมบัติแล้วส่งคืนรายการอาร์เรย์ใหม่

array.map(function(item) { 
    delete item.bad; 
    return item; 
});

13
โปรดทราบว่าสิ่งนี้ทำให้อาร์เรย์ดั้งเดิมกลายพันธุ์
piotr_cz

1
ในกรณีreturnนี้ไม่จำเป็นต้องมีคำชี้แจงที่ชัดเจน
Sandeep Kumar

4
array.forEach(v => delete v.bad);
Anthony Awuley


9

วิธีแก้ปัญหาโดยใช้ต้นแบบจะทำได้ก็ต่อเมื่อวัตถุของคุณเหมือนกัน:

function Cons(g) { this.good = g; }
Cons.prototype.bad = "something common";
var array = [new Cons("something 1"), new Cons("something 2"), …];

แต่มันก็ง่าย (และO(1)):

delete Cons.prototype.bad;

5

สำหรับความเห็นของฉันนี่เป็นตัวแปรที่ง่ายที่สุด

array.map(({good}) => ({good}))

3
คำถามเกี่ยวกับการขจัดความไม่ดีไม่รักษาความดี หากออบเจ็กต์ของคุณมี 10 ช่องที่ต้องเก็บและอีกช่องที่ต้องลบด้านบนจะยาวมากในการพิมพ์
Adrien

1

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

data.map((datum)=>{
                    return {
                        'id':datum.id,
                        'title':datum.login,
                    }

0

ฉันจะแนะนำให้ใช้Object.assignภายในforEach()ลูปเพื่อให้วัตถุถูกคัดลอกและไม่ส่งผลต่ออาร์เรย์ดั้งเดิมของวัตถุ

var res = [];
array.forEach(function(item) { 
    var tempItem = Object.assign({}, item);
    delete tempItem.bad; 
    res.push(tempItem);
});
console.log(res);

0

คำถามนี้เก่าไปหน่อย แต่ฉันต้องการเสนอทางเลือกอื่นที่ไม่กลายพันธุ์ข้อมูลต้นทางและต้องใช้ความพยายามเพียงเล็กน้อย:

function mapOut(sourceObject, removeKeys = []) {
  const sourceKeys = Object.keys(sourceObject);
  const returnKeys = sourceKeys.filter(k => !removeKeys.includes(k));
  let returnObject = {};
  returnKeys.forEach(k => {
    returnObject[k] = sourceObject[k];
  });
  return returnObject;
}

const array = [
  {"bad": "something", "good":"something"},
  {"bad":"something", "good":"something"},
];

const newArray = array.map(obj => mapOut(obj, [ "bad", ]));

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


0

ฉันได้ลองหาวัตถุใหม่โดยไม่ต้องลบ coulmns ใน Vue.js

let data =this.selectedContactsDto[];

// selectedContactsDto [] = วัตถุที่มีรายการวัตถุอาร์เรย์ที่สร้างขึ้นในโครงการของฉัน

console.log (ข้อมูล); ให้ newDataObj = data.map (({groupsList, customFields, firstname, ... item}) => item); console.log ("newDataObj", newDataObj);


0

ในการลบอาร์เรย์อ็อบเจ็กต์ฟอร์มคู่ค่าคีย์บางส่วนให้ใช้Postgres SQLเป็นฐานข้อมูลดังตัวอย่างนี้:

นี่คือฟังก์ชันผู้ใช้ส่งคืนวัตถุรายละเอียดผู้ใช้เราต้องลบคีย์ "api_secret" ออกจากแถว:

    function getCurrentUser(req, res, next) { // user function
    var userId = res.locals.userId;
    console.log(userId)
    db.runSQLWithParams("select * from users where id = $1", [userId], function(err, rows) {
      if(err){
        console.log(err)
      }
      var responseObject = {
        _embedded: rows,
      }
      responseObject._embedded[0].api_secret = undefined
      // console.log(api);
      // console.log(responseObject);
      res.json(responseObject);
    }); 
}

ฟังก์ชันข้างต้นส่งคืนวัตถุด้านล่างเป็นการตอบสนอง JSON ก่อนหน้านี้

 {
    "_embedded": [
        {
            "id": "0123abd-345gfhgjf-dajd4456kkdj",
            "secret_key: "secret",
            "email": "abcd@email.com",
            "created": "2020-08-18T00:13:16.077Z"
        }
    ]
}

หลังจากเพิ่มบรรทัดนี้responseObject._embedded[0].api_secret = undefinedแล้วจะให้ผลลัพธ์ด้านล่างเป็นการตอบสนอง JSON:

{
        "_embedded": [
            {
                "id": "0123abd-345gfhgjf-dajd4456kkdj",
                "email": "abcd@email.com",
                "created": "2020-08-18T00:13:16.077Z"
            }
        ]
    }


0

มีห้องสมุดมากมาย ทุกอย่างขึ้นอยู่กับความซับซ้อนของโครงสร้างข้อมูลของคุณ (เช่นพิจารณาคีย์ที่ซ้อนกันลึก ๆ )

เราชอบออบเจ็กต์ฟิลด์เนื่องจากมันทำงานกับลำดับชั้นที่ซ้อนกันอย่างลึกซึ้ง (สร้างสำหรับพารามิเตอร์ฟิลด์ api) นี่คือตัวอย่างโค้ดง่ายๆ

// const objectFields = require('object-fields');

const array = [
  { bad: 'something', good: 'something' },
  { bad: 'something', good: 'something' }
];

const retain = objectFields.Retainer(['good']);
retain(array);
console.log(array);
// => [ { good: 'something' }, { good: 'something' } ]
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-fields@2.0.19"></script>

ข้อจำกัดความรับผิดชอบ : ฉันเป็นผู้เขียนฟิลด์วัตถุ



-4

var array = [{"bad": "something", "good":"something"},{"bad":"something", "good":"something"}];
var results = array.map(function(item){
  return {good : item["good"]}
});
console.log(JSON.stringify(results));


คุณช่วยอธิบายวิธีแก้ปัญหาของคุณได้ไหม
sg7

แผนที่เป็นโครงสร้างข้อมูลใหม่ใน JavaScript ES6 ลิงค์ที่แนบมาอาจช่วยคุณได้ hackernoon.com/what-you-should-know-about-es6-maps-dc66af6b9a1e
hk_y

วิธีนี้ไม่ดีถ้าคุณมีอุปกรณ์ประกอบฉากหลายชิ้นในสิ่งของของคุณ
Koop4

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