Javascript 如何在函数样式的对象数组中仅更改一个特定对象?
让我们假设我们想要创建一些可读性很强的代码,然后执行以下操作:Javascript 如何在函数样式的对象数组中仅更改一个特定对象?,javascript,functional-programming,underscore.js,code-readability,Javascript,Functional Programming,Underscore.js,Code Readability,让我们假设我们想要创建一些可读性很强的代码,然后执行以下操作: 遍历列表的所有元素 除一个特定元素外,对所有元素进行同等更改(即使多个元素可以满足搜索条件) 返回包含已更改元素的列表 使用下划线power 例如,我想将属性isChosen和true值仅添加到具有hasRoom属性的第一个元素,其他元素应该为这个新属性hasRoom获得false值 下面是使用下划线库创建的代码: var i = 0 var changedList = [] _.each(list, function(
isChosen
和true
值仅添加到具有hasRoom
属性的第一个元素,其他元素应该为这个新属性hasRoom
获得false
值
下面是使用下划线库创建的代码:
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)
})
这段代码可以工作,但我认为可以有更好的方法来实现这一点,也许可以使用u.chain()
因此,作为输入,我们可以
[
{hasRoom: false},
{hasRoom: true},
{hasRoom: true}
]
因此,我们应该
[
{hasRoom: false, isChosen: false},
{hasRoom: true, isChosen: true},
{hasRoom: true, 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;
函数优先(数组、过滤器函数){
var指数,len=array.length;
对于(索引=0;索引
请注意,
\u js
还定义了数组上的第一个
函数,但它更适用于猫
或头
函数。您可以就语义进行争论。您可以使用通常称为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;
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);
函数优先(数组、过滤器函数){
var指数,len=array.length;
对于(索引=0;索引
请注意,
\u js
还定义了数组上的第一个
函数,但它更适用于猫
或头
函数。你可以争论语义学
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 } ]
输出
[ { hasRoom: true, isChosen: true },
{ hasRoom: true, isChosen: false },
{ isChosen: false } ]
在功能性风格中,您可以这样做:
// 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;
});
在功能性风格中,您可以这样做:
// 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语句将仅在找到第一个有房间的位置之前执行。此解决方案修改设置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)
最后,我的代码开始如下所示:
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)
您必须创建一个新对象吗?至于代码可读性标记,当您可以使用布尔值时,为什么要使用数字?@user1066946此代码块位于函数addPropertyToOnlyOneElement(列表)内,它应该返回已更改的列表您必须创建新对象吗?至于代码可读性标记,当你可以使用布尔值时,为什么要使用数字?@user1066946此代码块位于函数addPropertyToOnlyOneElement(列表)内,它应该返回更改的列表如果你将所有内容都放在全局范围内,JavaScript中也有for-each,JavaScript中没有for-each;仅适用于中的
。我们处理的是数组而不是对象,因此不需要使用中的for
。这是一个概念验证代码,用于演示first
的工作原理,将您的全球范围关注点带到相关的地方。你的评论是错误和误导性的。你确定你的代码比问题中的代码可读性更好吗?有Array.prototype.forEach
和for-in循环,在编辑问题之前,你将答案中的每个变量都放在全局范围内,答案的长度是问题的两倍。对不起,我使用了Chrome,我不知道你在运行IE8,你把所有的东西都放在全局范围内,JavaScript中有一个for-each,JavaScript中没有for-each;仅适用于中的。我们处理的是数组而不是对象,因此不需要使用中的for
。这是一个概念验证代码,用于演示first
的工作原理,将您的全球范围关注点带到相关的地方。你的评论是错误和误导性的。你确定你的代码比问题中的代码可读性更好吗?有Array.prototype.forEach
和for-in循环,在编辑问题之前,你将答案中的每个变量都放在全局范围内,答案的长度是问题的两倍。对不起,我使用了Chrome,不知道你在运行IE8