【发布时间】:2018-04-28 09:14:42
【问题描述】:
我在从嵌套数组对象中检索“独占”过滤数据时遇到了一些问题(基本 JS 嵌套和过滤)。该代码适用于 React 项目。如果需要,我可能会介绍 lodash。
我有一个数组,其中包含 1 个或多个(也可能是 0,在这种情况下返回默认值)字符串:
let arrayA = ["string-1", "string-2"]; //assume them to be skill slugs
我声明了一个新数组来保存稍后推入其中的数据:
let newArr1 = [];
我的嵌套主数组:
/*Top level skillset category, within each of which a skills array resides (propC).
Within each skill there is an array of projects associated with that particular skill (propC3).
Projects can have multiple skills so projects in one skill may perhaps reside in other skills as well.*/
let arrayB =[ //the top level skillset category
{
"propA": "valueA1",
"propB": "valueB1",
"propC":[ //the skills array
{
"propC1": "valueC11",
"matchthis": "string-1", //the unique skill slug
"proppC2": "valueC12",
"propC3": [ //projects
{
propC31: "valueC131",
},
{
propC32: "valueC132",
}
]
},
{
"propC1": "valueC12",
"matchthis": "string-2",
"proppC2": "valueC12",
"propC3": [
{
propC31: "valueC131",
},
{
propC32: "valueC232",
}
]
}
],
"propD": "valueD1"
},
{
"propA": "valueA2",
"propB": "valueB2",
"propC":[
{
"propC1": "valueC21",
"matchthis": "string-2",
"proppC2": "valueC22",
"proppC3": [
{
propC31: "valueC231",
},
{
propC32: "valueC132",
}
]
}
],
"propD": "valueD1"
},
]
我需要过滤我的arrayB 嵌套数组,以便仅返回基于arrayA 数组中的字符串的数据子集。我使用newArray1 数组来保存这些数据。我可以有重复的数据(当我推入newArray 数组时),所以我也可以通过vanilla JS 或lodash 删除它们。
我的尝试:
arrayA.map((a,i)=>{
return arrayB.filter((b,j)=>{
return b.propC.filter((c,k)=>{
return a===c.matchthis
}).map((o,i)=>{
o.propC3.map((o,i)=>{
newArr1.push(o)
})
})
})
})
当我推送数据时,可能会出现重复,因此我接下来将其删除:
// newArr1 = newArr1.filter((s1, pos, arr) => arr.findIndex((s2)=>s2.project_id === s1.project_id) === pos); //JS
newArr1 = _.uniqBy(newArr1, 'project_id'); //lodash
我似乎无法获得exclusion。排他性我的意思是驻留在newArray1(项目)中的数据应该只有具有arrayA 中传递的所有技能的项目——如果一个失败没有结果。如果我通过了["html5", "css", "react"],那么只有包含这些技能的项目才会被退回。
按照我目前的方法,我可以获得“包容性”的结果。
因此场景是:用户选择一个或多个技能(从技能集合中),然后我显示包含所有这些技能的项目(独家方法)。由于技能存在于类别中,因此技能有时可以存在于多个类别中。我可能有一个开关,允许用户在包含和排除过滤之间进行选择,但绝对不是现在。
这里或多或少是实际的数组对象,为简洁起见:
[{
skillltype_id:”0”,
skills: [
{
skill_id: ”0”,
skill_name: "HTML5”,
skill_slug:"html5”,
….
projects: [
{
project_id :”0”,
project_name: “Lorem Ipsum 1”,
project_slug: “a-slug”
…
},
{
project_id :”2”,
project_name: “Lorem Ipsum 2”,
project_slug: “b-slug”
…
},
….
]
},
{
skill_id: ”2”,
skill_name: “javascript”,
skill_slug:”javascript”,
….
projects: [
{
project_id :”100”,
project_name: “Lorem Ipsum 1”,
project_slug: “a-slug”
…
},
{
project_id :”2”,
project_name: “Lorem Ipsum 2”,
project_slug: “b-slug”
…
},
….
]
}
],
skilltype_description:"Lorem Ipsum”,
skilltype_name:”Lorem Ipsum”,
skilltype_shortdescription:"Lorem Ipsum”,
},
……..
……
]
更新:添加想要的结果:
基于此问题顶部显示的示例数组,将["html5","css"] 传递为arrayA
应该返回一个数组,其中包含包含在arrayB 中的项目列表 > propC > propC3 作为newArray1(或任何名称),其中arrayA 中的每个元素都与matchthis 匹配propC 中的财产。
如果只有一个字符串匹配(例如html5),那么它不能被考虑并且将返回一个空数组。所有传递的字符串都必须匹配才能被视为独占。
为了更加清楚:基于具有接近实际数据的 arrayB 示例(接近问题的结尾),将 ["html5","css"] 作为数组传递
应返回包含在skills > projects 中的项目数组,其中每个元素(字符串)与skills 数组中的skill_slug 属性匹配。
-
arrayA是我将用于搜索的值的数组 -
arrayB是技能组类别数组,由名为propC的技能数组组成。 -
propC中的每个技能都包含一个名为propC3的项目数组,并且还有一个matchthis属性,可用于匹配来自arrayA的字符串。
更新 2:为清楚起见添加更多信息
该项目使用redux 和thunks 所以绝对是非变异的原则。我没有提到这一点,因为我认为这个特定问题更像是一个基本的 JS 基础问题。
此特定代码部分在调度之前位于action creator 中。
我不得不提一下,我在前面几行从getState() 函数参数(redux 存储返回的对象)中做了一个slice() 以获得arrayB,所以基本上是我在这里添加的代码是可变的,因为我正在制作一个独特的副本。最终的数组(newArray1)将作为状态的有效负载传递。
因此,如果创建一个新数组(实际上newArray1 是一个新创建的数组,只是为了保存来自过滤操作的数据)或者现有的(此处添加的代码)数组是否发生了变异,这并不重要.
我还认为,可能不需要创建一个新数组来保存过滤后的数据,并且可以通过多个链接的map 和filter 和类似方法来解决。但到目前为止,希望在早期开发过程中保持简单。
这是我的第一个 react-redux 项目(除了研究项目),所以我会尽量小心改变状态,有时会过度创建副本。
流程:
- 用户选择一个技能,我发送一个动作并将技能 slug 添加到商店中存在的
selectedskill数组中 - 以上是
Promise,因此在then中,我会根据所选技能发送一个用于显示相关项目的操作 - 这个动作就是问题所在。我使用
getState()和slice()从商店(arrayB) 中获取skillsets对象的副本,其中包含所有技能组,每个技能组都具有技能并且每个技能还包括匹配的项目。我也有可用的selectedskills数组(arrayA)。现在我需要匹配它们并过滤掉嵌套的独家项目(arrayB>propC>propC3) - 假设我获得了我想要的数据(使用新数组或仅通过映射和过滤器的多个链接)我将此数组作为有效负载返回,以便分派给减速器,以便我的 UI 现在将显示与所有选定的技能。
- (附注:我有所有可用项目的数组。很早,当页面打开时,我从所有
skillsets和skills中提取所有这些项目,并在重复数据删除后将它们保留为如果需要,我可以使用一个大而独特的allprojects数组。我没有像我想的那样使用它,考虑到数据是有限的,所以我的skillsets数组不会太大,我可以继续使用它作为主要来源数据并在需要时使用)
【问题讨论】:
-
请同时添加想要的结果。
-
我想知道为什么投反对票。一个有效的理由有助于确保未来的问题没有相同的问题。这个问题很详细。也许太长了。还添加了对“想要的结果”部分的(有效)建议编辑。
-
您添加了描述,这很好,但不是对象本身,这将有助于回答问题。
-
好的。我认为这是一个没有评论的匿名行动。我希望现在通过编辑问题更清楚了。
-
不,不是。例如,您需要一个新数组吗?原始数据是否发生变异有关系吗?
标签: javascript arrays dictionary filter redux