按最大重复次数对嵌套数组的对象数组进行计数和排序

时间:2017-08-16 07:46:13

标签: javascript jquery sorting multidimensional-array javascript-objects

这听起来似乎已经得到了解答,但我在StackOverflow上尝试了很多解决方案。没有解决我的问题。我有一个复杂的嵌套arras和数据集数组,其中包含更多嵌套的子集或列表。我想将它们合并下来和/或找到一种通过某些键对重复项进行计数和排序的方法。这是我的真实数据: 的修改

      var arr =[  
   {  
      "Brand 1":[  
         {  
            "NAME":"SHIRT",
            "SIZE":"M"
         },
         {  
            "NAME":"PANTS",
            "SIZE":"L"
         }
      ],
      "Brand 2":[  
         {  
            "NAME":"JEANS",
            "SIZE":"S"
         },
         {  
            "NAME":"TROUSER",
            "SIZE":"S"
         },
         {  
            "NAME":"TROUSERS",
            "SIZE":"L"
         }
      ],
      "Brand 3":[  
         {  
            "SIZE":"L",
            "NAME":"JEANS"
         }
      ]
   },
   {  
      "Brand x":[  
         {  
            "NAME":"SNEAKERS",
            "SIZE":"M"
         }
      ],
      "Brand 2":[  
         {  
            "NAME":"BLAZER",
            "SIZE":"L"
         },
         {  
            "NAME":"FUR COAT",
            "SIZE":"L"
         }
      ],
      "Brand 1":[  
         {  
            "SIZE":"XL",

            "NAME":"BLAZER"
         }
      ]
   }
]

子集的数量不固定。正如您所看到的,这是一个复杂的阵列,并且那里的解决方案不会超过2个级别或1个维度。期望的输出: 的修改

      var arr =  [  
   {  
      "Brand 1":[  
         {  
            "NAME":"SHIRT",
            "SIZE":"M"
         },
         {  
            "NAME":"PANTS",
            "SIZE":"L"
         },
         {  
            "COUNT":"3"
         }
      ],
      "Brand 2":[  
         {  
            "NAME":"JEANS",
            "SIZE":"S"
         },
         {  
            "NAME":"TROUSER",
            "SIZE":"S"
         },
         {  
            "NAME":"TROUSERS",
            "SIZE":"L"
         },
         {  
            "COUNT":"5"
         }
      ],
      "Brand 3":[  
         {  
            "SIZE":"L",
            "NAME":"JEANS"
         },
         {  
            "COUNT":"3"
         }
      ]
   },
   {  
      "Brand x":[  
         {  
            "NAME":"SNEAKERS",
            "SIZE":"M"
         },
         {  
            "COUNT":"1"
         }
      ]
   }
]

你能看到每个品牌阵列末尾的“COUNT”变量吗?这就是我想要的东西,并根据它对物品进行分类。

我已经在stackoveflow上尝试过标准排序解决方案,包括连接和合并以及展平。没有适当的解决方案对我有用。 提前感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

嵌套数据结构,特别是在键和值之间传播的信息,很难处理。我建议您将对象转换为普通对象的平面列表(如果需要,将密钥放入这些对象中),并使用此列表作为进一步处理的基础,如聚合。

这就是这种转换的方式:

var arr = [
    {
        "Brand 1": [
            {
                "NAME": "SHIRT",
                "SIZE": "M"
            },
            {
                "NAME": "PANTS",
                "SIZE": "L"
            }
        ],
        "Brand 2": [
            {
                "NAME": "JEANS",
                "SIZE": "S"
            },
            {
                "NAME": "TROUSER",
                "SIZE": "S"
            },
            {
                "NAME": "TROUSERS",
                "SIZE": "L"
            }
        ],
        "Brand 3": [
            {
                "SIZE": "L",
                "NAME": "JEANS"
            }
        ]
    },
    {
        "Brand x": [
            {
                "NAME": "SNEAKERS",
                "SIZE": "M"
            }
        ],
        "Brand 2": [
            {
                "NAME": "BLAZER",
                "SIZE": "L"
            },
            {
                "NAME": "FUR COAT",
                "SIZE": "L"
            }
        ],
        "Brand 1": [
            {
                "SIZE": "XL",

                "NAME": "BLAZER"
            }
        ]
    }
];

// build a flat list of objects

let isScalar = x => typeof x !== 'object' || x === null;
let isPlain = x => isScalar(x) || Object.values(x).every(isScalar);

function *flat(obj) {
    if (isPlain(obj))
        yield obj;

    else if (Array.isArray(obj))
        for (let x of obj)
            yield *flat(x);

    else
        for (let key of Object.keys(obj))
            for (let val of flat(obj[key]))
                yield Object.assign(val, {key});
}


let all = [...flat(arr)];

// aggregation examples

let count = function(values) {
    let m = new Map();
    for (let x of values)
        m.set(x, (m.get(x) || 0) + 1);
    return [...m.entries()];
}

let byBrand = count(all.map(x => x.key));
console.log(byBrand);

let bySize = count(all.map(x => x.SIZE));
console.log(bySize);