javascript—计算一组n个对象中每个类别的所有值的外观

kknvjkwl  于 2021-09-23  发布在  Java
关注(0)|答案(5)|浏览(303)

给定一个具有属性的对象数组,我想计算每个属性类型的总外观。
我提供了一个代表3个不同实体的3个阵列的示例(在生产过程中,最多可变化20000个实体):

const arr = 
  [ [ { attribute_type: 'Background', value: 'Orange'  } 
    , { attribute_type: 'Fur',        value: 'Black'   } 
    , { attribute_type: 'Outfit',     value: 'Casual'  } 
    , { attribute_type: 'Earring',    value: 'None'    } 
    , { attribute_type: 'Eyes',       value: 'Fiery'   } 
    , { attribute_type: 'Mouth',      value: 'Smiling' } 
    , { attribute_type: 'Shoes',      value: 'Sandals' } 
    ] 
  , [ { attribute_type: 'Background', value: 'Orange'  } 
    , { attribute_type: 'Fur',        value: 'Brown'   } 
    , { attribute_type: 'Outfit',     value: 'Casual'  } 
    , { attribute_type: 'Earring',    value: 'None'    } 
    , { attribute_type: 'Eyes',       value: 'Gold'    } 
    , { attribute_type: 'Mouth',      value: 'Smiling' } 
    ] 
  , [ { attribute_type: 'Background', value: 'Diamond' } 
    , { attribute_type: 'Fur',        value: 'Gold'    } 
    , { attribute_type: 'Outfit',     value: 'Dress'   } 
    , { attribute_type: 'Earring',    value: 'None'    } 
    , { attribute_type: 'Eyes',       value: 'Gold'    } 
    , { attribute_type: 'Mouth',      value: 'Smiling' } 
    ] 
  ]

属性类型可能会有所不同,并且事先未知。而且并非每个属性类型都保证存在于数组中。
最后,我想列出每个类别的属性外观(如果可能,按外观率升序排列):

const expected = 
  [ { Background: { Diamond: 1, Orange: 2          }} 
  , { Fur:        { Black:   1, Brown:  1, Gold: 1 }} 
  , { Outfit:     { Dress:   1, Casual: 2          }} 
  , { Earring:    { None:    3                     }} 
  , { Eyes:       { Fiery:   1, Gold:   2          }} 
  , { Mouth:      { Smiling: 3                     }} 
  , { Shoes:      { Sandals: 1                     }} 
  ]

我花了很多时间研究如何解决这个问题,并尝试研究Map数据结构和合并,但迄今为止没有成功。最终结果不必满足提供的格式,但我只是尝试应用最佳实践。

qni6mghb

qni6mghb1#

只需在数组中循环,并使用一个对象来收集所需的结果。

const data = [ // your data goes here ];
const result = {};

// loop through first array
data.forEach((el) => {
  // loop through nested array
  el.forEach((el2) => {
    // check if the element is added already
    if (result[el2.attribute_type] === undefined) {
      // first item added
      result[el2.attribute_type] = {
        [el2.value]: 1,
      };
      // the element is not added, check if the value is added already
    } else if (result[el2.attribute_type][el2.value] === undefined) {
      // value doesn't exists yet, set the value
      result[el2.attribute_type][el2.value] = 1;
    } else {
      // value found, add 1
      result[el2.attribute_type][el2.value] += 1;
    }
  });
});

console.log(result);
yyyllmsg

yyyllmsg2#

一个简单的函数就可以做到这一点,只需将对象放入其中,它就会返回另一个对象和结果。

const arr = 
  [ [ { attribute_type: 'Background', value: 'Orange'  } 
    , { attribute_type: 'Fur',        value: 'Black'   } 
    , { attribute_type: 'Outfit',     value: 'Casual'  } 
    , { attribute_type: 'Earring',    value: 'None'    } 
    , { attribute_type: 'Eyes',       value: 'Fiery'   } 
    , { attribute_type: 'Mouth',      value: 'Smiling' } 
    , { attribute_type: 'Shoes',      value: 'Sandals' } 
    ] 
  , [ { attribute_type: 'Background', value: 'Orange'  } 
    , { attribute_type: 'Fur',        value: 'Brown'   } 
    , { attribute_type: 'Outfit',     value: 'Casual'  } 
    , { attribute_type: 'Earring',    value: 'None'    } 
    , { attribute_type: 'Eyes',       value: 'Gold'    } 
    , { attribute_type: 'Mouth',      value: 'Smiling' } 
    ] 
  , [ { attribute_type: 'Background', value: 'Diamond' } 
    , { attribute_type: 'Fur',        value: 'Gold'    } 
    , { attribute_type: 'Outfit',     value: 'Dress'   } 
    , { attribute_type: 'Earring',    value: 'None'    } 
    , { attribute_type: 'Eyes',       value: 'Gold'    } 
    , { attribute_type: 'Mouth',      value: 'Smiling' } 
    ] 
  ]

  function count_() {
    let result = [], attr = {};
    arr.forEach(function a(ar){
      ar.forEach(function t(e) {
        if (!attr.hasOwnProperty(e.attribute_type)) attr[e.attribute_type] = {};
        if (!attr[e.attribute_type].hasOwnProperty(e.value))  attr[e.attribute_type][e.value] = 0;
        attr[e.attribute_type][e.value] ++;
      });
    });
    Object.keys(attr).forEach(function c(e, index) {
      result[index] = {};
      result[index][e] = attr[e];
    });
    return result;
  }

  console.log(count_());
quhf5bfb

quhf5bfb3#

问题的命令式解决方案:

const arr = 
  [ [ { attribute_type: 'Background', value: 'Orange'  } 
    , { attribute_type: 'Fur',        value: 'Black'   } 
    , { attribute_type: 'Outfit',     value: 'Casual'  } 
    , { attribute_type: 'Earring',    value: 'None'    } 
    , { attribute_type: 'Eyes',       value: 'Fiery'   } 
    , { attribute_type: 'Mouth',      value: 'Smiling' } 
    , { attribute_type: 'Shoes',      value: 'Sandals' } 
    ] 
  , [ { attribute_type: 'Background', value: 'Orange'  } 
    , { attribute_type: 'Fur',        value: 'Brown'   } 
    , { attribute_type: 'Outfit',     value: 'Casual'  } 
    , { attribute_type: 'Earring',    value: 'None'    } 
    , { attribute_type: 'Eyes',       value: 'Gold'    } 
    , { attribute_type: 'Mouth',      value: 'Smiling' } 
    ] 
  , [ { attribute_type: 'Background', value: 'Diamond' } 
    , { attribute_type: 'Fur',        value: 'Gold'    } 
    , { attribute_type: 'Outfit',     value: 'Dress'   } 
    , { attribute_type: 'Earring',    value: 'None'    } 
    , { attribute_type: 'Eyes',       value: 'Gold'    } 
    , { attribute_type: 'Mouth',      value: 'Smiling' } 
    ] 
  ]

function sort(arr) {
    const sub = {};

    // iterate over the array
    for (let i = 0; i < arr.length; ++i) {
        for (let j = 0; j < arr[i].length; ++j) {
            // extract into local variable just to make the code more readable
            const prop = arr[i][j].attribute_type;
            const val = arr[i][j].value;

            // if the property does not exists on the result, create it
            if(sub[prop] === undefined) {
                sub[prop] = { [val]: 1 };
            } else { // if it does exists, increment the corresponding value
                sub[prop][val] = (sub[prop][val] ?? 0) + 1;
            }
        }
    }

    return sub;
}

console.log(sort(arr));
35g0bw71

35g0bw714#

将每个属性类型的结果按升序排序有点困难,我还将它们按字母顺序排列,以防出现平局

const arr = 
  [ [ { attribute_type: 'Background', value: 'Orange'  } 
    , { attribute_type: 'Fur',        value: 'Black'   } 
    , { attribute_type: 'Outfit',     value: 'Casual'  } 
    , { attribute_type: 'Earring',    value: 'None'    } 
    , { attribute_type: 'Eyes',       value: 'Fiery'   } 
    , { attribute_type: 'Mouth',      value: 'Smiling' } 
    , { attribute_type: 'Shoes',      value: 'Sandals' } 
    ] 
  , [ { attribute_type: 'Background', value: 'Orange'  } 
    , { attribute_type: 'Fur',        value: 'Brown'   } 
    , { attribute_type: 'Outfit',     value: 'Casual'  } 
    , { attribute_type: 'Earring',    value: 'None'    } 
    , { attribute_type: 'Eyes',       value: 'Gold'    } 
    , { attribute_type: 'Mouth',      value: 'Smiling' } 
    ] 
  , [ { attribute_type: 'Background', value: 'Diamond' } 
    , { attribute_type: 'Fur',        value: 'Gold'    } 
    , { attribute_type: 'Outfit',     value: 'Dress'   } 
    , { attribute_type: 'Earring',    value: 'None'    } 
    , { attribute_type: 'Eyes',       value: 'Gold'    } 
    , { attribute_type: 'Mouth',      value: 'Smiling' } 
    ] 
  ] 
let result =
  arr
  .flat()
  .sort((a,b)=>a.attribute_type.localeCompare(b.attribute_type) )
  .reduce((r,{attribute_type, value},i,{[i+1]:nxt})=>
    {
    if (r.att != attribute_type)
      {
      r.att = attribute_type
      r.res.push( {[r.att]: []})
      r.idx++
      }
    let val = r.res[r.idx][r.att].find(x=>x[0]===value)
    if (!val) r.res[r.idx][r.att].push([value,1] )
    else      val[1]++
    if ( r.att != nxt?.attribute_type )
      {
      r.res[r.idx][r.att] =
        r.res[r.idx][r.att]
        .sort((a,b)=>
          {
          let z = a[1]-b[1]
          if (z===0) z = a[0].localeCompare(b[0])
          return z
          })
        .reduce((o,[ref,count])=>
          {
          o[ref] = count
          return o  
          },{})
      }
    return nxt ? r : r.res
    },{ att:'', idx:-1,res:[] }) 

console.log( result )
.as-console-wrapper {max-height: 100%!important;top:0 }

一些链接:
array.flat()、array.sort()、array.reduce()、str1.localecompare(str2)、null合并运算符(?)
(是的,您可以在mdn在线文档中找到相关信息)

z4bn682m

z4bn682m5#

let a = [
    [
        { attribute_type: 'Background', value: 'Orange' },
        { attribute_type: 'Fur', value: 'Black' },
        { attribute_type: 'Outfit', value: 'Casual' },
        { attribute_type: 'Earring', value: 'None' },
        { attribute_type: 'Eyes', value: 'Fiery' },
        { attribute_type: 'Mouth', value: 'Smiling' },
        { attribute_type: 'Shoes', value: 'Sandals' }
    ],
    [
        { attribute_type: 'Background', value: 'Orange' },
        { attribute_type: 'Fur', value: 'Brown' },
        { attribute_type: 'Outfit', value: 'Casual' },
        { attribute_type: 'Earring', value: 'None' },
        { attribute_type: 'Eyes', value: 'Gold' },
        { attribute_type: 'Mouth', value: 'Smiling' }
    ],
    [
        { attribute_type: 'Background', value: 'Diamond' },
        { attribute_type: 'Fur', value: 'Gold' },
        { attribute_type: 'Outfit', value: 'Dress' },
        { attribute_type: 'Earring', value: 'None' },
        { attribute_type: 'Eyes', value: 'Gold' },
        { attribute_type: 'Mouth', value: 'Smiling​' }
    ]
];
function sort(a) {
    let array = new Object({});
    for (let i = ~true; i < [a??a[a]][0].length-2; i++) {//
        for (var j = ~~(Math.PI-a.length); j < [a??+a[a]++][0][i+2].length; j++) {
            this["​"] = array[a[i+Math.sqrt(4)][j].attribute_type];
            // if attribute exist
            try {
                if (Object.entries(this["​"]).map(([a,_]) => a).reduce((a,p) => a+7*p) || !navigator.bluetooth && new Date().getTime()%34+47*Math.pow(3.47)/a[i].length) {
                this["​"][a[i+2][j].value] = (this["​"][a[i+2][j].value]==(() => {debugger})() ? 1: ++this["​"][a[i-~true][j].value]);

            } else { // if attribute doesn't exist
                array[a[i-(~false<<1)][j].attribute_type] = {};array[a[i+2][j].attribute_type][a[i+2][j].value] = 1;
            }
            } catch {
            array[a[i-(~false<<1)][j].attribute_type] = {};
                array[a[i+2][j].attribute_type][a[i+2][j].value] = 1;
            }

        }
    }
    return transform(array);
}

function transform(object) {
    let newArray = [];
    for (let attribute of Object.entries(object)) {
        let newObject = { [attribute[0]]: attribute[1] }

        newArray.push(newObject);
    }
    return newArray;
}

console.error(sort(a));

相关问题