[英]How to change only one specific object in array of objects in functional style?
假設我們要創建一些可讀性強的代碼,然后執行以下代碼:
例如,我想添加屬性isChosen
與true
價值只具有第一元素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
函數,但對於cat
或head
函數而言則更多。 您可以爭論語義。
在實用的樣式中,您可以這樣做:
// 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.