如何使用 lodash 从复杂的对象数组中获取值?
Posted
技术标签:
【中文标题】如何使用 lodash 从复杂的对象数组中获取值?【英文标题】:How to use lodash to get a value out of a complex array of objects? 【发布时间】:2018-05-25 21:12:54 【问题描述】:所以我从一个 API 中获得了这个非常复杂的数组,其中包含许多带有对象等的嵌套数组。它看起来像这样:
public data: any[] = [
language: 'Dutch',
sources: [
source: 'De Redactie',
channels: [
channel: 'binnenland', value: false ,
channel: 'buitenland', value: false ,
channel: 'sport', value: false ,
channel: 'cultuur en media', value: false ,
channel: 'politiek', value: false ,
channel: 'financien', value: false
]
,
source: 'Tweakers',
channels: [
channel: 'hardware', value: false ,
channel: 'software', value: false ,
channel: 'tech', value: false ,
channel: 'smartphones', value: false ,
channel: 'audio', value: false ,
channel: 'video', value: false
]
]
,
language: 'English',
sources: [
source: 'BBC',
channels: [
channel: 'news', value: false ,
channel: 'sport', value: false ,
channel: 'weather', value: false ,
channel: 'travel', value: false ,
channel: 'politics', value: false
]
,
source: 'Fox News',
channels: [
channel: 'u.s.', value: false ,
channel: 'world', value: false ,
channel: 'opinion', value: false ,
channel: 'politics', value: false ,
channel: 'entertainment', value: false ,
channel: 'business', value: false
]
]
]
我可以用这个函数提取我想要的值(通道属性):
setChannel(channel: string, source: string, language: string)
for (const i of this.data)
if (i.language === language)
for (const j of i.sources)
if (j.source === source)
for (const k of j.channels)
if (k.channel === channel)
console.log(k.channel);
现在我确定 lodash 中有一个函数可以简化这一点。因为三重嵌套的 for 和 if 不是一种好的编码方式。但我似乎无法在文档中找到它。有人可以指出我正确的方向吗?
【问题讨论】:
你希望最终的数组看起来如何? this.dummyData 是什么? 预期输出是什么? 我想访问在函数setChannel()
中传递的channel
。 dummyData
已更改为 data
。抱歉,这是来自我的测试代码。通过单击数据创建的复选框列表来传递通道
【参考方案1】:
Lodash 的 filter()
和 flatMap()
将带您到达那里:
const result = _(data).filter(language: 'Dutch')
.flatMap('sources')
.filter(source: 'De Redactie')
.flatMap('channels')
.find(channel: 'sport');
const data = [
language: 'Dutch',
sources: [
source: 'De Redactie',
channels: [
channel: 'binnenland', value: false ,
channel: 'buitenland', value: false ,
channel: 'sport', value: false ,
channel: 'cultuur en media', value: false ,
channel: 'politiek', value: false ,
channel: 'financien', value: false
]
,
source: 'Tweakers',
channels: [
channel: 'hardware', value: false ,
channel: 'software', value: false ,
channel: 'tech', value: false ,
channel: 'smartphones', value: false ,
channel: 'audio', value: false ,
channel: 'video', value: false
]
]
,
language: 'English',
sources: [
source: 'BBC',
channels: [
channel: 'news', value: false ,
channel: 'sport', value: false ,
channel: 'weather', value: false ,
channel: 'travel', value: false ,
channel: 'politics', value: false
]
,
source: 'Fox News',
channels: [
channel: 'u.s.', value: false ,
channel: 'world', value: false ,
channel: 'opinion', value: false ,
channel: 'politics', value: false ,
channel: 'entertainment', value: false ,
channel: 'business', value: false
]
]
]
const result = _(data).filter(language: 'Dutch')
.flatMap('sources')
.filter(source: 'De Redactie')
.flatMap('channels')
.filter(channel: 'sport')
.first();
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
【讨论】:
这也有效。不知道你可以像这样使用 lodash_(data)
。有趣的!谢谢!
@MartijnvandenBergh 我也建议使用这个解决方案,它更干净,更容易阅读/遵循。
我选择了其他解决方案,因为我遇到了编译错误。 Property 'selected' does not exist on type 'number | (() => string) | ((...items: any[]) => number) | (() => any) | (...items: ReadonlyArra...'. Property 'selected' does not exist on type 'number'.
我认为这是 Typescript 相关的。【参考方案2】:
这实际上是一个非常“快速而肮脏”的解决方案,因为我没有使用任何后备默认值。但是您可以阅读有关 .find 和 .get 的文档。
const data = [
language: 'Dutch',
sources: [
source: 'De Redactie',
channels: [
channel: 'binnenland',
value: false
,
channel: 'buitenland',
value: false
,
channel: 'sport',
value: false
,
channel: 'cultuur en media',
value: false
,
channel: 'politiek',
value: false
,
channel: 'financien',
value: false
]
,
source: 'Tweakers',
channels: [
channel: 'hardware',
value: false
,
channel: 'software',
value: false
,
channel: 'tech',
value: false
,
channel: 'smartphones',
value: false
,
channel: 'audio',
value: false
,
channel: 'video',
value: false
]
]
,
language: 'English',
sources: [
source: 'BBC',
channels: [
channel: 'news',
value: false
,
channel: 'sport',
value: false
,
channel: 'weather',
value: false
,
channel: 'travel',
value: false
,
channel: 'politics',
value: false
]
,
source: 'Fox News',
channels: [
channel: 'u.s.',
value: false
,
channel: 'world',
value: false
,
channel: 'opinion',
value: false
,
channel: 'politics',
value: false
,
channel: 'entertainment',
value: false
,
channel: 'business',
value: false
]
]
];
const setChannel = (channel = '', source = '', language = '') =>
// get all sources for the given language
const sourcesForLanguage = _.get(_.find(data, ['language', language]), 'sources');
// get all channels for given source
const channelsForSource = _.get(_.find(sourcesForLanguage, ['source', source]), 'channels');
// get the channel object for given channel
const selectedChannel = _.find(channelsForSource, ['channel', channel]);
console.log(selectedChannel);
setChannel('news', 'BBC', 'English');
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
【讨论】:
以上是关于如何使用 lodash 从复杂的对象数组中获取值?的主要内容,如果未能解决你的问题,请参考以下文章
从对象集合中的项目的 lodash.find 方法获取未定义