嵌套循环两个数组以按类别排序

问题描述 投票:0回答:5

let arr = [
     {
          name: 'siggaret',
          type: 'tobbako'
     },
     {
          name: 'fanta',
          type: 'liquid'
     },
     {
          name: 'potato',
          type: 'vegetables'
     },
     {
          name: 'tvorog',
          type: 'milk'
     },
     {
          name: 'steak',
          type: 'meat'
     },
     {
          name: 'kent',
          type: 'tobbako'
     },
     {
          name: 'cola',
          type: 'liquid'
     },
     {
          name: 'potato',
          type: 'vegetables'
     },
     {
          name: 'tvorog',
          type: 'milk'
     },
     {
          name: 'steak',
          type: 'meat'
     },
     {
          name: 'sheep',
          type: 'meat'
     }
]

let categories = [
     {
          type: 'vegetables',
          arr: [],
          count: 0
     },
     {
          type: 'tobbako',
          arr: [],
          count: 0
     },
     {
          type: 'liquid',
          arr: [],
          count: 0
     },
     {
          type: 'other',
          arr: [],
          count: 0
     }
]

/*
    
*/


for (let item of arr) {
     for (let category of categories) {
          if(item.type === category.type){
               category.arr.push(item.name)
               category.count++
          } else {
               category.arr.push(item.name)
               category.count++
          }
     }
}

console.log(categories)

有哪些项目没有添加到其他项目中?有什么问题吗?

我尝试按类别对所有项目进行排序。

嵌套循环效果不佳,但我尝试使用 for of ,但排序时存在一些问题。

当我尝试按 item.name 和 Category.type 排序时,所有项目的名称都会添加到所有类别中。

我有两个数组,我需要找到两者之间的差异并将它们显示在无序列表中。

我可以循环遍历主数组以进行一场匹配,但我不知道如何循环遍历主列表以查找多个键值并高效地执行此操作。

以下是每个数组中键值的摘录:

javascript arrays object nested-loops for-of-loop
5个回答
1
投票

您可以将类别转换为对象,而不是循环两个数组,其中类别类型是键,因此您可以仅使用

type
作为键:

let arr = [
     {
          name: 'siggaret',
          type: 'tobbako'
     },
     {
          name: 'fanta',
          type: 'liquid'
     },
     {
          name: 'potato',
          type: 'vegetables'
     },
     {
          name: 'tvorog',
          type: 'milk'
     },
     {
          name: 'steak',
          type: 'meat'
     },
     {
          name: 'kent',
          type: 'tobbako'
     },
     {
          name: 'cola',
          type: 'liquid'
     },
     {
          name: 'potato',
          type: 'vegetables'
     },
     {
          name: 'tvorog',
          type: 'milk'
     },
     {
          name: 'steak',
          type: 'meat'
     },
     {
          name: 'sheep',
          type: 'meat'
     }
]

let categories = {
     'vegetables': {
          arr: [],
          count: 0
     },
     'tobbako': {
          arr: [],
          count: 0
     },
     'liquid': {
          arr: [],
          count: 0
     },
     'other': {
          arr: [],
          count: 0
     }
}


for (let item of arr) {
  //get category object or fallback to "other"
  const category = categories[item.type] || categories.other;
  category.arr.push(item.name)
  category.count++
}

console.log(categories)

// now we can get an array sorted by count of our categories name
const sortedByCount = Object.keys(categories) //get array of types
  .sort((a,b) => categories[b].count - categories[a].count) // sort by count
  .map(type => type + " = "  + categories[type].count); // append count

console.log("categories sorted by count", sortedByCount);

//or convert it into array w/sorted names
const categoriesArray = Object.keys(categories) //get array of types
  .map(type => //convert types into objects
  {
    const category = Object.assign({}, categories[type]); //clone object
  //  const category = categories[type]; //don't clone object
    category.type = type;

    category.arr = [...category.arr].sort(); //clone array and sort it
  //  category.arr.sort(); //sort array of names without clonning
    return category;
  })
  .sort((a,b) => b.count - a.count); //sort by count
console.log("categories as array sorted by count w / sorted names", categoriesArray);
.as-console-wrapper{top:0;max-height:unset!important;overflow:auto!important;}


0
投票

在您的代码中,

if () { ... } else { ... }
的两个分支运行相同的代码。您应该删除
else { ... }
分支。

像这样:

for (let item of arr) {
     for (let category of categories) {
          if (item.type === category.type){
               category.arr.push(item.name);
               category.count++;
          }
     }
}

0
投票

问题出在 else 语句中,基本上,您不需要 else 语句,因为如果您看到代码,它们都是相同的,在您的情况下,您要将项目添加到类别中,所以删除 else 语句:

for (let item of arr){
   for (let category of categories) {
      if(item.type === category.type){
          category.arr.push(item.name);
           category.count++;
        }
     }
  }

0
投票

您可以使用

Object.values()
Array#reduce()
方法的组合,如下所示,然后使用
sort
map
对数组进行排序:

const 
    arr = [ { name: 'siggaret', type: 'tobbako' }, { name: 'fanta', type: 'liquid' }, { name: 'potato', type: 'vegetables' }, { name: 'tvorog', type: 'milk' }, { name: 'steak', type: 'meat' }, { name: 'kent', type: 'tobbako' }, { name: 'cola', type: 'liquid' }, { name: 'potato', type: 'vegetables' }, { name: 'tvorog', type: 'milk' }, { name: 'steak', type: 'meat' }, { name: 'sheep', type: 'meat' } ],
    
    categories = Object.values(
        arr.reduce(
            (acc,{name,type}) => 
              ({
                ...acc,[type]:{
                  type,
                  arr:[...(acc[type] && acc[type]?.arr || []),name],
                  count:(acc[type] && acc[type].count || 0) + 1
                }
              }), {}
        )
    )
    .sort((a,b) => a.type.localeCompare(b.type))
    .map(({type,arr,count}) => ({type,arr:arr.sort((a,b) => a.localeCompare(b)),count}));
    
    console.log( categories );


0
投票

良好的开端。 问题出在你的 else 语句中。发生的事情是:

else {
    category.arr.push(item.name)
    category.count++
}

触发过于频繁。每次类别不匹配时就会推送。

如何修复:您需要在该循环之外处理“推送到“其他”部分”。

© www.soinside.com 2019 - 2024. All rights reserved.