通过映射数组需要帮助

时间:2019-04-07 13:29:50

标签: javascript arrays

我有一个与db有6个不同日期的数组:

[{"_id":{"source":"2019-04-06","status":false},"count":1},
{"_id":{"source":"2019-04-06","status":true},"count":1},
{"_id":{"source":"2019-03-24","status":false},"count":2},
{"_id":{"source":"2019-03-24","status":true},"count":1},
{"_id":{"source":"2019-03-23","status":false},"count":3},
{"_id":{"source":"2019-03-08","status":false},"count":1},
{"_id":{"source":"2019-02-02","status":true},"count":1},
{"_id":{"source":"2019-02-02","status":false},"count":2},
{"_id":{"source":"2019-01-29","status":false},"count":1}]

我需要的是2个数组,其长度为6个项目,并且值为“ count” 如果只有状态“ true”存在某个日期,那么我需要将一个计数:“ 0”推入错误数组。 而且,如果某个日期只存在状态“ false”,那么我需要将一个计数:“ 0”推送到true数组。

它应该像这样:

Arrayforstatusfalse = [1,2,3,1,2,1]
Arrayforstatustrue = [1,1,0,0,1,0]

但是我得到的是这个

Arrayforstatusfalse = [1,2,3,1,2,1]
Arrayforstatustrue = [1,1,1]

更新: 对不起,这个丑陋的代码。我会更精确的。并感谢您的帮助。

this.responsedata = input  
this.line1 = output for all the "false"
this.line2 = output for all the "true"

我使用条件循环输入数据并将其推入新数组:

  for (var i=0; i<this.responsedata.length;i++) {
       if (this.responsedata[i]._id.status === true ) {
          console.log('true exits for date: ' + JSON.stringify(this.responsedata[i]._id.source) + JSON.stringify(this.responsedata[i].count) )
          this.line2.push(this.responsedata[i])
       }
       if (this.responsedata[i]._id.status === false ) {
         console.log('false exits for date: ' + JSON.stringify(this.responsedata[i]._id.source) + JSON.stringify(this.responsedata[i].count) )
         this.line1.push(this.responsedata[i])
      }
  }

控制台:

[Log] false exits for date: "2019-04-06"1
[Log] true exits for date: "2019-04-06"1
[Log] false exits for date: "2019-03-24"2
[Log] true exits for date: "2019-03-24"1
[Log] false exits for date: "2019-03-23"3
[Log] false exits for date: "2019-03-08"1
[Log] true exits for date: "2019-02-02"1
[Log] false exits for date: "2019-02-02"2
[Log] false exits for date: "2019-01-29"1
[Log] line1[1,2,3,1,2,1]
[Log] line2[1,1,1]

这里我需要line2 = [1,1,0,0,1,0] 因为我需要一个“如果没有在这个日期退出”则为0。.

6 个答案:

答案 0 :(得分:1)

您可以使用Map来按给定数据的插入顺序保持相同的索引。

var array = [{ _id: { source: "2019-04-06", status: false }, count: 1 }, { _id: { source: "2019-04-06", status: true }, count: 1 }, { _id: { source: "2019-03-24", status: false }, count: 2 }, { _id: { source: "2019-03-24", status: true }, count: 1 }, { _id: { source: "2019-03-23", status: false }, count: 3 }, { _id: { source: "2019-03-08", status: false }, count: 1 }, { _id: { source: "2019-02-02", status: true }, count: 1 }, { _id: { source: "2019-02-02", status: false }, count: 2 }, { _id: { source: "2019-01-29", status: false }, count: 1 }],
    result = array.reduce((m => (r, { _id: { source, status }, count }) => {
        var index = m.get(source);
        if (index === undefined) {
            m.set(source, index = m.size);
            r.true[index] = 0;
            r.false[index] = 0;                    
        }
        r[status][index] = count;
        return r;
    })(new Map), { true: [], false: [] }),
    { true: trues, false: falses } = result;

console.log(...trues);
console.log(...falses);

答案 1 :(得分:0)

您可以使用reduce()使用源作为键将数组汇总为一个对象。使用Object.entries将对象转换为数组,然后再次缩小以将内部子对象转换为数组。

使用destructuring assignment syntax来分配变量。

let array = [{"_id":{"source":"2019-04-06","status":false},"count":1},{"_id":{"source":"2019-04-06","status":true},"count":1},{"_id":{"source":"2019-03-24","status":false},"count":2},{"_id":{"source":"2019-03-24","status":true},"count":1},{"_id":{"source":"2019-03-23","status":false},"count":3},{"_id":{"source":"2019-03-08","status":false},"count":1},{"_id":{"source":"2019-02-02","status":true},"count":1},{"_id":{"source":"2019-02-02","status":false},"count":2},{"_id":{"source":"2019-01-29","status":false},"count":1}];

let {Arrayforstatusfalse,Arrayforstatustrue} = Object.entries(array.reduce((c, v) => {
    c.Arrayforstatustrue[v._id.source] = c.Arrayforstatustrue[v._id.source] || 0;
    c.Arrayforstatusfalse[v._id.source] = c.Arrayforstatusfalse[v._id.source] || 0;
    if (v._id.status) c.Arrayforstatustrue[v._id.source] += v.count;
    else c.Arrayforstatusfalse[v._id.source] += v.count;
    return c;
  }, {Arrayforstatusfalse: {},Arrayforstatustrue: {}}))
  .reduce((c, [k, o]) => Object.assign(c, {[k]: Object.values(o)}), {});

console.log(Arrayforstatusfalse);
console.log(Arrayforstatustrue);

答案 2 :(得分:0)

这吗?

const data = [
  {"_id":{"source":"2019-04-06","status":false},"count":1},
  {"_id":{"source":"2019-04-06","status":true},"count":1},
  {"_id":{"source":"2019-03-24","status":false},"count":2},
  {"_id":{"source":"2019-03-24","status":true},"count":1},
  {"_id":{"source":"2019-03-23","status":false},"count":3},
  {"_id":{"source":"2019-03-08","status":false},"count":1},
  {"_id":{"source":"2019-02-02","status":true},"count":1},
  {"_id":{"source":"2019-02-02","status":false},"count":2},
  {"_id":{"source":"2019-01-29","status":false},"count":1},
];

const byDate = {};
data.forEach((f, ndx) => {
  byDate[f._id.source] = byDate[f._id.source] || [];
  byDate[f._id.source].push(f);
});

function mapCounts(byDate, status) {
  return Object.values(byDate).map(d => {
    const ndx = d.findIndex(e => e._id.status === status);
    return ndx >= 0 ? d[ndx].count : 0;
  });
}
const falseForDate = mapCounts(byDate, false);
const trueForDate = mapCounts(byDate, true);

console.log(falseForDate.join(','));
console.log(trueForDate.join(','));

请注意,我很好奇这是出于什么目的。如果同一日期中有3个日期,则上面的代码将无法处理任何事情,因为否则有2个计数为true或2个计数为false。使用哪个计数。类似地,如果同一日期的2个真或2个假(相同的问题),则出现相同的现象。也许您想按日期对真或假的计数求和?

在这种情况下

const data = [
  {"_id":{"source":"2019-04-06","status":false},"count":1},
  {"_id":{"source":"2019-04-06","status":true},"count":1},
  {"_id":{"source":"2019-03-24","status":false},"count":2},
  {"_id":{"source":"2019-03-24","status":true},"count":1},
  {"_id":{"source":"2019-03-23","status":false},"count":3},
  {"_id":{"source":"2019-03-08","status":false},"count":1},
  {"_id":{"source":"2019-02-02","status":true},"count":1},
  {"_id":{"source":"2019-02-02","status":false},"count":2},
  {"_id":{"source":"2019-01-29","status":false},"count":1},
];

const byDate = {};
data.forEach((f, ndx) => {
  byDate[f._id.source] = byDate[f._id.source] || [];
  byDate[f._id.source].push(f);
});

function mapCounts(byDate, status) {
  return Object.values(byDate).map(d => {
    return d.reduce((acc, e) => acc + (e._id.status === status ? e.count : 0), 0); 
  });
}
const falseForDate = mapCounts(byDate, false);
const trueForDate = mapCounts(byDate, true);

console.log(falseForDate.join(','));
console.log(trueForDate.join(','));

const data = [
  {"_id":{"source":"2019-04-06","status":false},"count":1},
  {"_id":{"source":"2019-04-06","status":true},"count":1},
  {"_id":{"source":"2019-03-24","status":false},"count":2},
  {"_id":{"source":"2019-03-24","status":true},"count":1},
  {"_id":{"source":"2019-03-23","status":false},"count":3},
  {"_id":{"source":"2019-03-08","status":false},"count":1},
  {"_id":{"source":"2019-02-02","status":true},"count":1},
  {"_id":{"source":"2019-02-02","status":false},"count":2},
  {"_id":{"source":"2019-01-29","status":false},"count":1},
];

const byDate = {};
data.forEach((f, ndx) => {
  byDate[f._id.source] = byDate[f._id.source] || [0, 0];
  byDate[f._id.source][f._id.status === true ? 1 : 0] += f.count;
});

const falseForDate = Object.values(byDate).map(v => v[0]);
const trueForDate = Object.values(byDate).map(v => v[1]);

console.log(falseForDate.join(','));
console.log(trueForDate.join(','));

答案 3 :(得分:0)

您可以获得唯一的来源(日期),并为每个true创建falsesource数组:

const dataArray = [{"_id":{"source":"2019-04-06","status":false},"count":1},
{"_id":{"source":"2019-04-06","status":true},"count":1},
{"_id":{"source":"2019-03-24","status":false},"count":2},
{"_id":{"source":"2019-03-24","status":true},"count":1},
{"_id":{"source":"2019-03-23","status":false},"count":3},
{"_id":{"source":"2019-03-08","status":false},"count":1},
{"_id":{"source":"2019-02-02","status":true},"count":1},
{"_id":{"source":"2019-02-02","status":false},"count":2},
{"_id":{"source":"2019-01-29","status":false},"count":1}];
// Get all sources
const sources = dataArray.map(item => item._id.source);
// Get unique sources
const uniqueSources = [...(new Set(sources))];

const arrayForStatusTrue = [];
const arrayForStatusFalse = [];

uniqueSources.forEach(source => {
  // Check if source with status true exists
  const itemWithStatusTrue = dataArray.find(item => (item._id.status && item._id.source === source));
  itemWithStatusTrue ? arrayForStatusTrue.push(itemWithStatusTrue.count) : arrayForStatusTrue.push(0);
  
  // Check if source with status false exists
  const itemWithStatusFalse = dataArray.find(item => (!item._id.status && item._id.source === source));
  itemWithStatusFalse ? arrayForStatusFalse.push(itemWithStatusFalse.count) : arrayForStatusFalse.push(0);
});

console.log(arrayForStatusTrue);
console.log(arrayForStatusFalse);

答案 4 :(得分:0)

您可以使用map来实现。它们在地图上的key将是source,值将是count。如果没有为特定的key找到值,则分配0。否则,根据给定条件分配值。

遍历inputArray的所有元素。迭代结束后,您将获得两个对象。只需使用Object.values()函数获取对象的值。

您完成了!!

我使用ternary operator来使代码看起来简短易懂。请参见下面的代码段

var inputArray = [{"_id":{"source":"2019-04-06","status":false},"count":1},{"_id":{"source":"2019-04-06","status":true},"count":1},{"_id":{"source":"2019-03-24","status":false},"count":2},{"_id":{"source":"2019-03-24","status":true},"count":1},{"_id":{"source":"2019-03-23","status":false},"count":3},{"_id":{"source":"2019-03-08","status":false},"count":1},{"_id":{"source":"2019-02-02","status":true},"count":1},{"_id":{"source":"2019-02-02","status":false},"count":2},{"_id":{"source":"2019-01-29","status":false},"count":1}];

var trueObjects = {},
  falseObjects = {};

inputArray.forEach(function(elem) {
  var index = elem._id.source,
    status = elem._id.status,
    count = elem.count;

  //initialize value for new index
  trueObjects[index] = trueObjects[index] ? trueObjects[index] : 0;
  falseObjects[index] = falseObjects[index] ? falseObjects[index] : 0;

  //set value based on condition
  trueObjects[index] = status ? count : trueObjects[index];
  falseObjects[index] = !status ? count : falseObjects[index];
});

trueArray = Object.values(trueObjects);
falseArray = Object.values(falseObjects);

console.log(falseArray);
console.log(trueArray);

答案 5 :(得分:0)

我建议每个日期使用Map创建一个条目(source),每个条目都有两个值代表两个可能状态的计数(初始化为零)。

然后将实际计数添加到这些条目中,最后将数据提取到您期望的两个数组中:

// Sample input
const array = [{ _id: { source: "2019-04-06", status: false }, count: 1 }, { _id: { source: "2019-04-06", status: true }, count: 1 }, { _id: { source: "2019-03-24", status: false }, count: 2 }, { _id: { source: "2019-03-24", status: true }, count: 1 }, { _id: { source: "2019-03-23", status: false }, count: 3 }, { _id: { source: "2019-03-08", status: false }, count: 1 }, { _id: { source: "2019-02-02", status: true }, count: 1 }, { _id: { source: "2019-02-02", status: false }, count: 2 }, { _id: { source: "2019-01-29", status: false }, count: 1 }];

// Algorithm
const map = new Map(array.map(o => [o._id.source, [0,0]]));
array.forEach(o => map.get(o._id.source)[+o._id.status] += o.count);
const [noes, ayes] = [0, 1].map(i => Array.from(map.values(), a => a[i]));

// Output
console.log(JSON.stringify(noes), JSON.stringify(ayes));