基于 Ramda.js 的数组过滤对象
Filter object base on an array with Ramda.js
let obj = {
tom: {
id: 0
},
david: {
id: 1
},
john: {
id: 2
}
}
let ids = [1, 2]
我想根据id过滤obj。
我想要的结果是
{
大卫: {
编号:1
},
约翰: {
编号:2
}
}
因为上面的ids是[1, 2].
我想用 Ramda.js 来做这个。
请帮帮我。
好的,对不起。
我做了这样的事情。
let obj2 = {}
ids.forEach((x) => {
obj2 += R.filter(y => y.id === x, obj)
})
obj = obj2
但是,这是不正确的。
而且我不想使用 forEach。
我想用 Ramda.js 做。
您可以在纯 JavaScript 中使用 Object.entries
并使用 includes
进行解构,如下所示:
let obj = {
tom: {
id: 0
},
david: {
id: 1
},
john: {
id: 2
}
};
let ids = [1, 2];
let result = {};
Object.entries(obj).forEach(([name, { id }]) => {
if (ids.includes(id)) {
result[name] = { id: id };
}
});
console.log(result);
您只能使用 Javascript
来做到这一点,首先您可以创建一个包含您想要保留的 ids
的集合(检查集合是否有一个元素是 O(1)
)。然后,您可以在原始 object
上循环并在新的 object
上添加 key
和他的 value
如果该集合具有相关的 id
:
let obj = {
tom: {id: 0},
david: {id: 1},
john: {id: 2}
}
let ids = [1, 2];
const filterByIds = (obj, ids) =>
{
let idsSet = new Set(ids);
let filteredObj = {};
for (k in obj)
{
if (idsSet.has(obj[k].id))
filteredObj[k] = obj[k];
}
return filteredObj;
}
console.log(filterByIds(obj, ids));
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
更新以使用 Ramda:
使用 Ramda,您可以这样做:
let obj = {
tom: {id: 0},
david: {id: 1},
john: {id: 2}
}
let ids = [1, 2];
let idsSet = new Set(ids);
const hasValidId = o => idsSet.has(o.id);
let res = R.filter(hasValidId, obj);
console.log(res);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
阅读文档就很容易了 here
试试这个:
let obj = { tom: { id: 0 }, david: { id: 1}, john: {id: 2} }
let ids = [1, 2] ;
let result = {} ;
for ( var o in obj ) {
if (ids.includes(obj[o].id))
result[o] = obj[o];
}
console.log(result) ;
一般来说,您应该努力使用对您有帮助而不是对您不利的数据结构。
使用如下所示的简化数据结构:
const obj = [
{id: 0, name: 'tom'},
{id: 1, name: 'david'},
{id: 2, name: 'john'}
]
您可以使用 innerJoin
:
innerJoin((cur, id) => cur.id === id, obj, [1, 2])
如何将原始数据结构转换为简化的数据结构?
使用 Ramda 可以分两步进行:
将您的对象拆分为 key/value 对数组 toPairs
:
{tom:{id:0}} ~> [['tom', {id: 0}]]
将每一对映射到一个对象中:
[['tom', {id: 0}]] ~> [{name: 'tom', id: 0}]
const obj = {
tom: {
id: 0
},
david: {
id: 1
},
john: {
id: 2
}
}
const convert = R.compose(R.map(([name, id]) => ({name, ...id})), R.toPairs);
console.log(convert(obj))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
除非这是学习 Ramda 的练习,否则请谨防想要在 Ramda 中执行此操作的想法。我是 Ramda 的主要作者之一,也是 Ramda 的忠实粉丝,但我需要强调的是,它只是一个工具包,在某些情况下无法提供帮助。当它有帮助时,很好,但它不应该成为目标。
现在,我确实认为它可以提供帮助。这就是我要用 Ramda 做的事情:
const matchIds = (obj, ids) => filter(propSatisfies(includes(__, ids), 'id'), obj)
let obj = {tom: {id: 0}, david: {id: 1}, john: {id: 2}}
let ids = [1, 2]
console.log(matchIds(obj, ids))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script>
const {__, filter, propSatisfies, includes} = R
</script>
另一种选择,尤其是当 id 列表比对象更不可能更改时,是这样的:
const matchIds = (ids) => filter(propSatisfies(includes(__, ids), 'id'))
let obj = {tom: {id: 0}, david: {id: 1}, john: {id: 2}}
let ids = [1, 2]
console.log(matchIds(ids)(obj))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script>
const {__, filter, propSatisfies, includes} = R
</script>
不喜欢占位符 ('__
') 有一些原因。如果您有这种感觉,可以将 includes(__, ids)
替换为 flip(includes)(ids)
.
更新
我不接受我自己的建议。虽然我仍然会为 filter
使用 Ramda,但这里不需要 propSatisfies
。一个简单的 lambda 就可以了:
const matchIds = (ids) => filter(({id}) => ids.includes(id))
至少在您习惯了偏应用的 Ramda 规范之后,这更加清晰易读。 (filter
有两个参数:谓词函数和要用它过滤的对象。因为我们只提供第一个,这给了我们一个期待第二个的函数。当我们用对象调用结果函数时,过滤发生了。)
我仍然会使用 Ramda 的 filter
的原因是它没有直接的内置版本应用于对象。 Ramda 提供了一种简单的替代方法来编写一次性对象过滤。
let obj = {
tom: {
id: 0
},
david: {
id: 1
},
john: {
id: 2
}
}
let ids = [1, 2]
我想根据id过滤obj。
我想要的结果是
{ 大卫: { 编号:1 }, 约翰: { 编号:2 } }
因为上面的ids是[1, 2].
我想用 Ramda.js 来做这个。
请帮帮我。
好的,对不起。
我做了这样的事情。
let obj2 = {}
ids.forEach((x) => {
obj2 += R.filter(y => y.id === x, obj)
})
obj = obj2
但是,这是不正确的。
而且我不想使用 forEach。
我想用 Ramda.js 做。
您可以在纯 JavaScript 中使用 Object.entries
并使用 includes
进行解构,如下所示:
let obj = {
tom: {
id: 0
},
david: {
id: 1
},
john: {
id: 2
}
};
let ids = [1, 2];
let result = {};
Object.entries(obj).forEach(([name, { id }]) => {
if (ids.includes(id)) {
result[name] = { id: id };
}
});
console.log(result);
您只能使用 Javascript
来做到这一点,首先您可以创建一个包含您想要保留的 ids
的集合(检查集合是否有一个元素是 O(1)
)。然后,您可以在原始 object
上循环并在新的 object
上添加 key
和他的 value
如果该集合具有相关的 id
:
let obj = {
tom: {id: 0},
david: {id: 1},
john: {id: 2}
}
let ids = [1, 2];
const filterByIds = (obj, ids) =>
{
let idsSet = new Set(ids);
let filteredObj = {};
for (k in obj)
{
if (idsSet.has(obj[k].id))
filteredObj[k] = obj[k];
}
return filteredObj;
}
console.log(filterByIds(obj, ids));
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
更新以使用 Ramda:
使用 Ramda,您可以这样做:
let obj = {
tom: {id: 0},
david: {id: 1},
john: {id: 2}
}
let ids = [1, 2];
let idsSet = new Set(ids);
const hasValidId = o => idsSet.has(o.id);
let res = R.filter(hasValidId, obj);
console.log(res);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
阅读文档就很容易了 here
试试这个:
let obj = { tom: { id: 0 }, david: { id: 1}, john: {id: 2} }
let ids = [1, 2] ;
let result = {} ;
for ( var o in obj ) {
if (ids.includes(obj[o].id))
result[o] = obj[o];
}
console.log(result) ;
一般来说,您应该努力使用对您有帮助而不是对您不利的数据结构。
使用如下所示的简化数据结构:
const obj = [
{id: 0, name: 'tom'},
{id: 1, name: 'david'},
{id: 2, name: 'john'}
]
您可以使用 innerJoin
:
innerJoin((cur, id) => cur.id === id, obj, [1, 2])
如何将原始数据结构转换为简化的数据结构?
使用 Ramda 可以分两步进行:
将您的对象拆分为 key/value 对数组
toPairs
:{tom:{id:0}} ~> [['tom', {id: 0}]]
将每一对映射到一个对象中:
[['tom', {id: 0}]] ~> [{name: 'tom', id: 0}]
const obj = {
tom: {
id: 0
},
david: {
id: 1
},
john: {
id: 2
}
}
const convert = R.compose(R.map(([name, id]) => ({name, ...id})), R.toPairs);
console.log(convert(obj))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
除非这是学习 Ramda 的练习,否则请谨防想要在 Ramda 中执行此操作的想法。我是 Ramda 的主要作者之一,也是 Ramda 的忠实粉丝,但我需要强调的是,它只是一个工具包,在某些情况下无法提供帮助。当它有帮助时,很好,但它不应该成为目标。
现在,我确实认为它可以提供帮助。这就是我要用 Ramda 做的事情:
const matchIds = (obj, ids) => filter(propSatisfies(includes(__, ids), 'id'), obj)
let obj = {tom: {id: 0}, david: {id: 1}, john: {id: 2}}
let ids = [1, 2]
console.log(matchIds(obj, ids))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script>
const {__, filter, propSatisfies, includes} = R
</script>
另一种选择,尤其是当 id 列表比对象更不可能更改时,是这样的:
const matchIds = (ids) => filter(propSatisfies(includes(__, ids), 'id'))
let obj = {tom: {id: 0}, david: {id: 1}, john: {id: 2}}
let ids = [1, 2]
console.log(matchIds(ids)(obj))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script>
const {__, filter, propSatisfies, includes} = R
</script>
不喜欢占位符 ('__
') 有一些原因。如果您有这种感觉,可以将 includes(__, ids)
替换为 flip(includes)(ids)
.
更新
我不接受我自己的建议。虽然我仍然会为 filter
使用 Ramda,但这里不需要 propSatisfies
。一个简单的 lambda 就可以了:
const matchIds = (ids) => filter(({id}) => ids.includes(id))
至少在您习惯了偏应用的 Ramda 规范之后,这更加清晰易读。 (filter
有两个参数:谓词函数和要用它过滤的对象。因为我们只提供第一个,这给了我们一个期待第二个的函数。当我们用对象调用结果函数时,过滤发生了。)
我仍然会使用 Ramda 的 filter
的原因是它没有直接的内置版本应用于对象。 Ramda 提供了一种简单的替代方法来编写一次性对象过滤。