繁体   English   中英

javascript中的丑陋嵌套forEach最佳实践

[英]ugly nested forEach in javascript best practise

嗨,我的代码感觉很hacky,我可以使用forloop来做同样的事情,这会提高性能,但看起来会更可怕。 有没有更清洁/最佳实践的方法?

这是我的数据模型

this.data = [
  {
    title: 'Math',
    img: this.mathImage,
    children: [
      {
        title: 'Calculus I & II',
        open: false,
        children: [
          {
            title: 'Differentials',
            open: false,
            children: [
              {
                title: 'Integration by parts',
                key: 'Differentials1',
                mainsub: 'Math',
                middlesub: 'Calculus I & II',
                lowsub: 'Differentials',
                saved: true // <--------------- HERE IS THE PROPERTY
              },
              {
                title: 'Integration by parts',
                key: 'Differentials2',
                mainsub: 'Math',
                middlesub: 'Calculus I & II',
                lowsub: 'Differentials',
                saved: true,
              },
            ]
          }
        ]
      }
    ]
  }
]

这是我的代码,将'saved'属性设置为false

removeFromFavoritesinSubjects(item) {
  this.data.forEach(list => {
    if (list.title === item.mainsub) {
      list.children.forEach(subitem => {
        if (subitem.title === item.middlesub) {
          subitem.children.forEach(items => {
            if (items.title === item.lowsub) {
              items.children.forEach(i => {
                if (i.key === item.key) {
                  i.saved = false;
                }
              })
            }
          })
        }
      })
    }
  })
} 

我将假设您只想在最低级别时将保存的值更改为false(即,在其他级别没有保存的属性)。

该答案使用for ... of递归遍历数组。

function changeSaved(data, key, value) {

  // loop through every object in the array
  for(var element in data){

    // see if there is a children node
    if(element.children){

      // run this function recursively on the children array
      changeSaved(element.children);

    } else {

      // no children key, set the value
      element[key] = value;
    }

  }

}

您可以这样称呼它:

changeSaved(data, 'saved', 'false');

线性搜索数据结构的效率非常低,如果您必须更频繁地执行此操作,则应该在item存储对对象的直接引用,或者使用允许按键高效查找的数据结构(例如Map )。

除了使用嵌套循环(用for … of .forEach()更好),我将使用链式.find()调用:

removeFromFavoritesinSubjects(item) {
  const list = this.data.find(list => list.title === item.mainsub);
  if (!list) return;
  const subitem = list.children.find(subitem => subitem.title === item.middlesub);
  if (!subitem) return;
  const items = subitem.children.find(items => items.title === item.lowsub);
  if (!items) return;
  const i = items.children.find(i => i.key === item.key);
  if (!i) return;
  i.saved = false;
}

(假定数组中没有重复项,并且每个removeFromFavouritesInSubjects()调用最多设置一个.saved属性)。

您可以利用递归和.reduce函数先对数据模型进行扁平化,然后轻松地对平面数据模型进行操作。

// flattenArray helper function turns nested array into flat array
function flattenArray (array) {
  return array.reduce((result, item) =>
    result.concat([ item ], flattenArray(item.children || []))
  , []);
}

// later in code
{
  // ...
  removeFromFavoritesInSubjects ({ key }) {
    // Consider all children are alongside with each other
    // [..., { title: 'Calculus I & II', ... }, { title: 'Differentials', ... }, ...]
    flattenArray(this.data).forEach(item => {
      if (item.key === key) {
        item.saved = false;
      }
    });
  }
  // ...
}

另外,也不必过于担心针对forEach使用for..loop性能。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM