簡體   English   中英

如何以功能樣式更改對象數組中的一個特定對象?

[英]How to change only one specific object in array of objects in functional style?

假設我們要創建一些可讀性強的代碼,然后執行以下代碼:

  1. 遍歷列表的所有元素
  2. 僅一個特定元素外,其他所有元素均等地更改(即使一個以上的元素可以滿足搜索條件)
  3. 返回此元素已更改的列表
  4. 使用_.underscore權力

例如,我想添加屬性isChosentrue價值只具有第一元素hasRoom財產,其他因素應該得到false值這個新屬性hasRoom

這是使用_.underscore lib創建的代碼:

  var i = 0
  var changedList = []
  _.each(list, function(el) {
    if (el.hasRoom && i === 0) {
      _.extend(el, { isChosen: true })
      i++
    } else {
      _.extend(el, { isChosen: false })
    }
    changedList.push(el)
  })

這段代碼有效,但是我認為可以有更好的方法,也許用_.chain()?

因此,作為輸入,我們可以擁有

[
    {hasRoom: false}, 
    {hasRoom: true}, 
    {hasRoom: true}
]

結果我們應該得到

[
    {hasRoom: false, isChosen: false}, 
    {hasRoom: true,  isChosen: true}, 
    {hasRoom: true,  isChosen: false}
]
var _ = require("underscore");
var data = [{hasRoom: true}, {hasRoom: true}, {}], found = false;

_.each(data, function(currentObject) {
    _.defaults(currentObject, {isChosen: false});
    if (found === false && currentObject.hasRoom) {
        found = currentObject.isChosen = true;
    }
});

console.log(data);

輸出量

[ { hasRoom: true, isChosen: true },
  { hasRoom: true, isChosen: false },
  { isChosen: false } ]

您可以使用通常稱為first的方法來找到與您的條件匹配的第一個元素:

function first (array, filter_function) {
    var index, len = array.length;
    for (index = 0; index < len; index += 1) {
        if (filter_function(array[index], index)) {
            return index;
        }
    }
    return -1;
}

rooms = [
    { hasRoom: false }, 
    { hasRoom: true }, 
    { hasRoom: true }
];

free_room = first(rooms, function (room) {
    return room.hasRoom;
});
if (free_room === -1) {
    throw "Dilbert lied!";
}
rooms[free_room].isChosen = true;

請注意, _js還在數組上定義了first函數,但對於cathead函數而言則更多。 您可以爭論語義。

在實用的樣式中,您可以這樣做:

// type: [a] -> (a -> Bool -> b) -> (a -> Bool) -> [b]
function changeFirstinList(list, change, predicate) {
    var first = true;
    return _.map(list, function(el) {
        return change(el, first && !(first = !predicate(el)));
    });
}

changeFirstinList([
    {hasRoom: false}, 
    {hasRoom: true}, 
    {hasRoom: true}
], function(el, isFirstwithpred) {
    return {hasRoom: el.hasRoom, isChosen: isFirstwithpred};
}, function(el) {
    return el.hasRoom;
});

此解決方案修改了設置isChosen的功能:

function notChosen(place){
  return false;
}

function chosen(place){
  if( !place.hasRoom ) return notChosen(place);
  setChosen = notChosen;
  return true;
}

var setChosen = chosen;

_.each(places, function(place){
    place.isChosen = setChosen(place);
});

if語句將只執行到找到帶有房間的第一個位置。

最后,我的代碼開始看起來像這樣:

function addChosenPropertyToFirstElementWithRooms(hotels) {
  var found = false
  return _.map(list, function(el) {
    return _.merge(el, { isChosen: isFirstElementWithRooms(el) })
  })

  function isFirstHotelWithRooms(el) {
    return found ? false : found = el.hasRoom
  }
}

而且功能的使用容易

var changedList = addChosenPropertyToFirstElementWithRooms(originalList)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM