แม็พผ่านคีย์การถุกรักษาวัตถุ


129

mapฟังก์ชั่นใน underscore.js ถ้าเรียกว่ามีวัตถุจาวาสคริปต์กลับอาร์เรย์ของค่าแมปจากค่าของวัตถุที่

_.map({one: 1, two: 2, three: 3}, function(num, key){ return num * 3; });
=> [3, 6, 9]

มีวิธีที่จะทำให้มันรักษากุญแจหรือไม่? เช่นฉันต้องการฟังก์ชั่นที่ส่งกลับ

{one: 3, two: 6, three: 9}

หากคุณอย่างฉันมาที่นี่เพื่อค้นหาฟังก์ชั่น like 'mapValues' ที่เปลี่ยนวัตถุจริงแทนที่จะส่งคืนใหม่ให้ตรวจสอบวิธีแก้ปัญหาง่ายๆนี้: stackoverflow.com/questions/30894044/ …
Michael Trouw

คำตอบ:


228

ด้วยการขีดเส้นใต้

ขีด_.mapObjectล่างมีฟังก์ชันเพื่อแมปค่าและเก็บรักษาคีย์

_.mapObject({ one: 1, two: 2, three: 3 }, function (v) { return v * 3; });

// => { one: 3, two: 6, three: 9 }

DEMO


ด้วยLodash

Lodash จัดให้มีฟังก์ชั่น_.mapValuesในการแมปค่าต่างๆ

_.mapValues({ one: 1, two: 2, three: 3 }, function (v) { return v * 3; });

// => { one: 3, two: 6, three: 9 }

DEMO


มีความพยายามที่จะได้รับฟังก์ชั่นลงใน _.mapValues ขีด: ฉบับที่เกี่ยวข้อง , ขอดึงสำหรับ _.mapValues ฉันหวังว่านี้จะต้องผ่าน :)
raffomania

ดูเหมือนว่าฉันจะทำให้วัตถุเป็นวัตถุหรือฉันไม่อยู่ในใจ
jsh

@jsh ในกรณี_.map()นี้กลับมา[['one', 3], ['two', 6], ['three', 9]]ซึ่งเป็นอาร์เรย์ของอาร์เรย์และ_.object()เปลี่ยนมันกลับเป็นวัตถุ
Jezen Thomas

56

ฉันจัดการเพื่อค้นหาฟังก์ชั่นที่ต้องการใน lodash ซึ่งเป็นยูทิลิตี้ไลบรารีที่คล้ายกับขีดล่าง

http://lodash.com/docs#mapValues

_.mapValues(object, [callback=identity], [thisArg])

สร้างวัตถุที่มีคีย์เดียวกับวัตถุและค่าที่สร้างขึ้นโดยการเรียกใช้คุณสมบัติที่นับได้ของวัตถุผ่านการเรียกกลับ การเรียกกลับถูกผูกไว้กับ thisArg และเรียกใช้ด้วยอาร์กิวเมนต์สามข้อ (ค่า, คีย์, วัตถุ)



13

ฉันรู้ว่ามันเก่า แต่ตอนนี้ขีดล่างมีแผนที่ใหม่สำหรับวัตถุ:

_.mapObject(object, iteratee, [context]) 

แน่นอนคุณสามารถสร้างแผนที่ที่ยืดหยุ่นสำหรับทั้งอาร์เรย์และวัตถุ

_.fmap = function(arrayOrObject, fn, context){
    if(this.isArray(arrayOrObject))
      return _.map(arrayOrObject, fn, context);
    else
      return _.mapObject(arrayOrObject, fn, context);
}

5
หมายเหตุสำหรับผู้ใช้ lodash: jdalton ได้ตัดสินใจที่จะทำลายความเข้ากันได้กับ underscore.jsมากกว่าการเปลี่ยนแปลงนี้ lodash จะไม่สนับสนุนmapObject; ดูmapValuesวิธีการของ lodash แทน
Mark Amery

13

แล้วรุ่นนี้ใน JS ธรรมดา ( ES6 / ES2015 ) ล่ะ?

let newObj = Object.assign(...Object.keys(obj).map(k => ({[k]: obj[k] * 3})));

jsbin

ถ้าคุณต้องการแมปบนวัตถุที่เรียกซ้ำ (แผนที่ซ้อนกัน obj) ก็สามารถทำได้ดังนี้:

const mapObjRecursive = (obj) => {
  Object.keys(obj).forEach(key => {
    if (typeof obj[key] === 'object') obj[key] = mapObjRecursive(obj[key]);
    else obj[key] = obj[key] * 3;
  });
  return obj;
};

jsbin

ตั้งแต่ES7 / ES2016คุณสามารถใช้Object.entriesแทนObject.keysดังนี้:

let newObj = Object.assign(...Object.entries(obj).map([k, v] => ({[k]: v * 3})));

5

ฉันรู้ว่ามันใช้เวลานานมาก แต่ก็ยังคงเป็นวิธีแก้ปัญหาที่ชัดเจนที่สุดผ่านทางโฟลเดส

function mapO(f, o) {
  return Object.keys(o).reduce((acc, key) => {
    acc[key] = f(o[key])
    return acc
  }, {})
}

ฉันไม่เป็นไรกับการใช้ห้องสมุด Lodash แต่โปรแกรมเมอร์กำลังใช้ห้องสมุดประเภทนี้และไม่รู้ว่าสิ่งนี้จะเกิดขึ้นได้อย่างไรใน vanilla JS ดังนั้นฉันขอขอบคุณคำตอบของคุณ!
cyonder

3

_.mapส่งคืน Array ไม่ใช่ Object

หากคุณต้องการวัตถุคุณดีกว่าการใช้ฟังก์ชั่นที่แตกต่างกันเช่นeach; ถ้าคุณต้องการใช้แผนที่คุณสามารถทำสิ่งนี้:

Object.keys(object).map(function(value, index) {
   object[value] *= 3;
})

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


ฉันมีความรู้สึกในการอ่านเอกสารที่มันไม่เป็นธรรมชาติเลยที่จะลองทำสิ่งนี้ใน underscore.js ฉันคิดว่ากรณีการใช้งานของฉันค่อนข้างเป็นธรรมชาติทำไมพวกเขาถึงไม่รองรับ
xuanji

เหตุผลหนึ่งอาจเป็นเพราะmapใช้ในการเปลี่ยนอินพุตที่สร้างอาร์เรย์เป็นเอาต์พุตคุณสามารถเขียน_.objectและ_.mapเป็น @GG เขียน แต่นั่นเป็นเรื่องของรสนิยม ณ จุดนี้
Alberto Zaccagni

3

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

mapValues = function(obj, f) {
  var k, result, v;
  result = {};
  for (k in obj) {
    v = obj[k];
    result[k] = f(v);
  }
  return result;
};


0

การแก้ไขมิกซ์สำหรับข้อบกพร่องแผนที่ขีดล่าง: P

_.mixin({ 
    mapobj : function( obj, iteratee, context ) {
        if (obj == null) return [];
        iteratee = _.iteratee(iteratee, context);
        var keys = obj.length !== +obj.length && _.keys(obj),
            length = (keys || obj).length,
            results = {},
            currentKey;
        for (var index = 0; index < length; index++) {
          currentKey = keys ? keys[index] : index;
          results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
        }
        if ( _.isObject( obj ) ) {
            return _.object( results ) ;
        } 
        return results;
    }
}); 

วิธีแก้ปัญหาง่ายๆที่เก็บคีย์ขวาและคืนเป็นวัตถุมันยังคงใช้วิธีเดียวกับแขก i คุณสามารถใช้ฟังก์ชันนี้เพื่อแทนที่ฟังก์ชัน bugy _.map

หรืออย่างที่ฉันใช้เป็น mixin

_.mapobj ( options , function( val, key, list ) 

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