Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 更新了嵌套属性,但没有多个循环_Javascript_Reactjs - Fatal编程技术网

Javascript 更新了嵌套属性,但没有多个循环

Javascript 更新了嵌套属性,但没有多个循环,javascript,reactjs,Javascript,Reactjs,我面临的一个问题是在JavaScript中操作数组或对象时总是重复自己的操作。我们正在逐渐远离jQuery时代,在这个时代,我们可以简单地将统计数据带入或从DOM中修改 以这个嵌套的对象数组为例 [ { "data": [ { "name": "item1", "checked": false }, { "name": "item2", "checked": false }

我面临的一个问题是在
JavaScript
中操作数组或对象时总是重复自己的操作。我们正在逐渐远离
jQuery
时代,在这个时代,我们可以简单地将统计数据带入或从
DOM
中修改

以这个嵌套的对象数组为例

[
  {
    "data": [
      {
        "name": "item1",
        "checked": false
      },
      {
        "name": "item2",
        "checked": false
      }
    ]
  }
]
为了更改
item2
checked
属性,我必须执行两个循环

const newData = data.map(o=>{
  return {
    ...o,
    data: o.data.map(o2=>{
     if(o2.name === 'item2'){
       return{
         ...o2,
         'checked': true
       }
     }
     return o2
   })
  }
})

是否有更好的解决此问题的方法?

这取决于您如何构造状态,例如,如果以这种方式表示相同的数据

{
 item1 : {name:"item1" ,checked:true} 
 ...
}
可能导致一个没有循环的简单操作,或者如果你有id,你也可以使用它们

了解normalizer确实有助于构建您的状态。

一种方法是认识到复杂数据结构中的每一层嵌套都是一个“函子”(这超出了解释它的回答范围,但在线上有很多很好的解释)

functors-101的解释是,它是“可映射性”概念的一个推广,因此可以映射数组、对象、可观测对象和各种奇怪的东西,同时保留它们的结构

无论如何,假设您的数据结构是嵌入在函子中的函子中的函子,您可以通过简单地将
map
函数自身与嵌套函子结构中的级别组合多次来映射最深的级别

例如,在您的情况下,您可以使用
map3
执行以下操作:

const result = map3(x => x.name === "item2" ? { ...x, checked: true } : x)(data)
这是一个完整的JS实现(我内联实现了FP库位,而不是使用依赖项来说明发生了什么):

//FP-utils(您可以使用像saccession或Ramda这样的库来获取这些文件)
常数合并=(o1,o2)=>({
…o1,
…氧气
})
const compose=fns=>fns.reduce((f,g)=>(…args)=>f(g(…args)))
常量mapArr=f=>a=>a.map(f)
常量mapObj=f=>o=>
对象。键(o)
.map(k=>({
[k] :f(o[k])
}))
.减少(合并)
const mapImpls=新映射([[Object,mapObj],[Array,mapArr]]
常量map=f=>x=>mapImpls.get(x.constructor)(f)(x)
const map2=compose([map,map])
const map3=compose([map,map,map])
const map4=compose([map,map,map,map])
// ...
//你的代码
常数数据=[
{
数据:[
{
名称:“项目1”,
勾选:假
},
{
名称:“项目2”,
勾选:假
}
]
}
]
常量投影=x=>
x、 名称==“项目2”
? {
…x,
核对:正确
}
:x
常量结果=map3(投影)(数据)
console.log(结果)
让您的\u数据=[
{
“数据”:[
{
“名称”:“项目1”,
“选中”:false
},
{
“名称”:“项目2”,
“选中”:false
}
]
}
]
让数据=[…您的_数据];
让index=0,mod=0,flag=false,rew_数组=[];
while(索引<数据长度){
如果(!标志){
新的_数组[索引]={…数据[索引]};
mod=data[index].data.length;
指数=0;
flag=true;
}否则{
设_index=new_array.length-1;
让数组=新数组[\uu索引]。数据;
if(数组[index].name=='item2'){
数组[索引]={
…数组[索引],
“选中”:true
}
}
如果(索引>模式){
索引=新的数组长度;
mod=0;
flag=false;
}
}
索引++;
}
控制台日志(数据);
因为您已经知道数据的结构,所以可以通过一个while循环来运行它,其中索引总是根据某个偏移量
mod
进行更改。在本例中,我使用
标志来告诉我何时检查外部数据或内部数据。并相应地更改索引


尽管,我必须承认,你最终还是要做同样数量的迭代,这一事实是无法回避的

最好根据您的需要构造数据结构,例如,并非总是需要数组来存储数据,普通对象也可以满足您的目的。如果数据是数组中的数组,则应执行
嵌套循环
,因为解决方案是
O(n^2)
复杂度。你无能为力。@VipinKumar如果这是一件简单的事情,那么结构很简单,但在某些情况下,结构“必须”很复杂。有很多方法可以解决这个问题。在纯函数式编程语言中,一种普遍存在的方法(在这种语言中,它们总是被迫像这样重构数据结构)是使用镜头。你可以做更多有趣的事情,比如利用每一层嵌套实际上是一个函子的事实。我会写一些例子作为答案。@Rajesh抱歉,我不明白你的意思。@Rajesh谢谢,我以前没有使用过这个功能。你有什么特别不明白的吗?那是双关语在多次阅读之后,我想这个解决方案对我的解决方案来说是如何更简单和可读的?我想这取决于您如何定义可读性。有些人认为将代码展平有助于他们更好地理解它。我想这就是你想要的,因为你的解决方案已经相当简洁了。如果你想让它更简单,你可以把你的对象构造成一个代理,然后创建一个api来轻松遍历它。或者把每个数组遍历分成两个独立的方法调用,然后把它抽象出来。同意第二点,Normalizer帮助,但你给我看的是一个对象,我需要对象数组。您可以从object.values获取对象数组
let your_data = [
    {
    "data": [
        {
        "name": "item1",
        "checked": false
        },
        {
        "name": "item2",
        "checked": false
        }
    ]
    }
]
let data = [...your_data];
let index = 0, mod = 0, flag = false, rew_array = [];
while(index < data.length){
    if(!flag){
        new_array[index] = {...data[index]};
        mod = data[index].data.length;
        index = 0;
        flag = true;
    }else{
        let __index = new_array.length-1;
        let array = new_array[__index].data;
        if(array[index].name === 'item2'){
            array[index] = {
                ...array[index],
                'checked': true
            }
        }
        if(index > mod) {
            index = new_array.length;
            mod = 0;
            flag = false;
        }
    }
    index++;
}

console.log(data);