2016-01-28 20 views
9

https://lodash.com/docs#mapKeysLàm thế nào để ánh xạ sâu các khóa đối tượng bằng JavaScript (lodash)?

Có thể ánh xạ khóa của đối tượng một cách sâu sắc bằng Lodash không? Nếu không, có thư viện nào khác cung cấp chức năng này (nếu được nhóm lại với chức năng thao tác lặp và sâu khác, thậm chí tốt hơn!)? Khác, làm thế nào sẽ đi về thực hiện điều này? Cuộc đấu tranh chính mà tôi thấy là xác định các đối tượng khóa/giá trị thuần túy một cách an toàn, có thể lặp lại sâu sắc. Thật dễ dàng để ném ra các mảng, nhưng điều quan trọng cần lưu ý là hàm không nên cố gắng lặp đi lặp lại sâu vào các đối tượng khác như một regex chẳng hạn.

Dành result-

var obj = { a: 2, b: { c: 2, d: { a: 3 } } }; 
_.deepMapKeys(obj, function (val, key) { 
    return val + '_hi'; 
}); 
// => { a_hi: 2, b_hi: { c_hi: 2, d_hi: { a_hi: 3 } } } 

Trả lời

21

Đây là cách bạn có thể làm điều đó trong lodash:

_.mixin({ 
    'deepMapKeys': function (obj, fn) { 

     var x = {}; 

     _.forOwn(obj, function(v, k) { 
      if(_.isPlainObject(v)) 
       v = _.deepMapKeys(v, fn); 
      x[fn(v, k)] = v; 
     }); 

     return x; 
    } 
}); 

và đây là một mixin trừu tượng hơn, mà đệ quy áp dụng bất kỳ mapper đưa ra:

_.mixin({ 
    deep: function (obj, mapper) { 
     return mapper(_.mapValues(obj, function (v) { 
      return _.isPlainObject(v) ? _.deep(v, mapper) : v; 
     })); 
    }, 
}); 

Cách sử dụng (trả về giống như trên):

obj = _.deep(obj, function(x) { 
    return _.mapKeys(x, function (val, key) { 
     return key + '_hi'; 
    }); 
}); 

Một tùy chọn khác, với cú pháp tao nhã hơn:

_.mixin({ 
    deeply: function (map) { 
     return function(obj, fn) { 
      return map(_.mapValues(obj, function (v) { 
       return _.isPlainObject(v) ? _.deeply(map)(v, fn) : v; 
      }), fn); 
     } 
    }, 
}); 


obj = _.deeply(_.mapKeys)(obj, function (val, key) { 
    return key + '_hi'; 
}); 
+0

Đây là giải pháp tuyệt vời vì vậy tôi sẽ upvote nó. Tuy nhiên, tôi thấy câu trả lời được chấp nhận đơn giản hơn trong việc giải quyết tùy chọn vì vậy đó là cách tiếp cận tôi muốn giới thiệu. –

+0

@TejasManohar: tốt, bạn đã yêu cầu mã đó là lodash dựa và có thể phân biệt giữa các đối tượng đơn giản và đã nhập ... câu trả lời được chấp nhận là không. – georg

+0

Bạn nói đúng. Tôi đã thay đổi điều này. –

1

EDIT: Điều này sẽ lập bản đồ các giá trị vật thể, chứ không phải các phím của nó. Tôi hiểu lầm câu hỏi.


function deepMap (obj, cb) { 
    var out = {}; 

    Object.keys(obj).forEach(function (k) { 
     var val; 

     if (obj[k] !== null && typeof obj[k] === 'object') { 
     val = deepMap(obj[k], cb); 
     } else { 
     val = cb(obj[k], k); 
     } 

     out[k] = val; 
    }); 

    return out; 
} 

Và sử dụng nó như

var lol = deepMap(test, function (v, k) { 
    return v + '_hi'; 
}); 

Nó sẽ đệ quy lặp trên một đối tượng sở hữu thuộc tính đếm được và gọi một CB đi qua nó giá trị hiện tại và quan trọng. Các giá trị trả lại sẽ thay thế giá trị hiện tại cho đối tượng mới. Nó không làm biến đổi đối tượng gốc.

Xem fiddle: https://jsfiddle.net/1veppve1/

+1

Điều quan trọng cần lưu ý là điều này trả về một đối tượng mới với các giá trị khác nhau, không phải là khóa - như được hỏi trong câu hỏi.Điều đó nói rằng, đó là một thay đổi đơn giản, và nó thể hiện sự hiểu biết khái niệm vì vậy tôi sẽ tiết kiệm một downvote :) –

+0

@TejasManohar Damn có xin lỗi tôi hiểu lầm điểm. Tôi nghĩ rằng bạn đã lập bản đồ giá trị không phải là chìa khóa. Ill thêm một chỉnh sửa để người khác không bị lẫn lộn. – ste2425

+0

Giải pháp có quá nhiều mã dự phòng –

1

Trong gia hạn câu trả lời của Georg, đây là những gì tôi đang sử dụng. Hỗn hợp mở rộng này bổ sung thêm khả năng ánh xạ mảng đối tượng trong đối tượng, một thay đổi đơn giản nhưng quan trọng.

_.mixin({ 
    deeply: function (map) { 
     return function (obj, fn) { 
     return map(_.mapValues(obj, function (v) { 
      return _.isPlainObject(v) ? _.deeply(map)(v, fn) : _.isArray(v) ? v.map(function(x) { 
      return _.deeply(map)(x, fn); 
      }) : v; 
     }), fn); 
     } 
    }, 
    }); 
0

Tôi đã thêm một cải tiến nhỏ từ Chris Jones's answer.

Mã sau khắc phục một số kết quả không mong đợi của các phần tử Mảng.

_.mixin({ 
    deeply: function (map) { 
    var deeplyArray = function (obj, fn) { 
     return obj.map(function(x) { 
     return _.isPlainObject(x) ? _.deeply(map)(x, fn) : x; 
     }) 
    } 

    return function (obj, fn) { 
     if (_.isArray(obj)) { 
     return deeplyArray(obj, fn); 
     } 

     return map(_.mapValues(obj, function (v) { 
     return _.isPlainObject(v) ? _.deeply(map)(v, fn) : _.isArray(v) ? 
      deeplyArray(v, fn) : v; 
     }), fn); 
    } 
    }, 
}); 
Các vấn đề liên quan