从JavaScript数组中获取句点的算法

时间:2018-02-05 21:20:00

标签: javascript arrays json underscore.js

我正在研究一种算法来查找对象的JSON数组中的句点。 JSON数组如下:

[
 {
   "year": 1960,
   "month": 1,
   "colval": 1
 },
 {
   "year": 1960,
   "month": 2,
   "colval": 1
 },
 {
   "year": 1960,
   "month": 3,
   "colval": 0
 },
 ....
 ....
 {
   "year": 2016,
   "month": 12,
   "colval": 0
 }]

此数组由包含"年","月"的对象组成。和" colval"。 (colval只能是0,1,2和3)

阵列从1960-1到2016-12开始,我希望获得colval> 0,此期间只能有1个零值。如果零值重复两次,则不计入期间。并且期限必须至少持续6个月。

例如:(仅显示colval的值)
粗体值是选定的时间段。

1-2-1-3-0-0-0-的 1-1-1-2-2-3-2-1-3-3-2 -0-0- 0- 1-2-2-2-0-3-3-3-3 -0-0-0-1-0-1-0-的 2-0-2- 2-3-3-3

我尝试用纯JS计算值,如果它大于0,当我访问两个"零"时将其设为零,但我仍然没有得到开始和结束的句点。

以下是我正在处理的代码:

        var counter = 0;
        var zeroCounter = 0;
        var startArray = null;          
        var periods = [];

        $.each(groupArr, function (i, v) {
            if (v.colval > 0) {
                if (counter == 0) {
                    startArray = v;
                }

                counter++;
            }
            else {
                if (zeroCounter > 1) {
                    if (counter > 5) {
                        endArray = v;
                        periods.push({ start: startArray, end: v });
                        startArray = null;
                        counter = 0;
                    }                       
                }
                else {
                    zeroCounter++;
                }
            }
        });

更新1:序列也无法以"零"开始或结束。

更新2:今天还增加了一项要求,即如果出现零之间有12个月,则此零也将添加到期间并继续其他数字。例如:

0-0- 1-1-0-1-2-2-1-3-1-2-2-3-2-2-3-0-2-1-1-3- 2 -0-0

更新3:由于"减少" IE中的函数支持,方法应该在Underscore中实现,以绕过浏览器支持问题。

更新4:新示例:

- &GT; 1-2-1-3-0-0-0-的 1-1-1-2-2-3-2-1-3-3-2 -0-0-0- < b> 1-2-2-2-0-3-3-3-3 -0-0-0-1-0-1-0-2-0-2-2-3-3- 3

- &GT; 0-0- 1-1-0-1-2-2-1-3-1-2-2-3-2-2-3-0-2-1-1-3-2 -0-0

- &GT; 1-1-3-0-1-0-0-的 1-0-1-2-3-2-2-2-3-1 -0-1-2-3-0 -1-2-0-0-0-1-2-3-3

  • 大胆的价值观可以接受。

2 个答案:

答案 0 :(得分:0)

你可以这样做:

var arr = [{"year": 1960,"month": 1,"colval": 1},{"year": 1960,"month": 10,"colval": 1},{"year": 1960,"month": 3,"colval": 0},{"year": 2016,"month": 12,"colval": 0 }];

var periods = arr.reduce((a, c, index, array) => {
  if(c.colval == 0 && index < (array.length - 1) && array[index + 1].colval == 0 && a[a.length - 1].length || (c.colval == 0 && a[a.length - 1].some(v => c.colval == 0))){
    a.push([]);
  }else{
    a[a.length - 1].push(c);
  }
  return a;
}, [[]]).reduce((a, c) => {
  if(c.length >= 2){
    c.sort((v1, v2) => ((v1.year + v1.month) - (v2.year + v2.month)));
    var minMonths = (c[0].year * 12) + c[0].month;
    var maxMonths = (c[c.length - 1].year * 12)  + c[c.length - 1].month;
    if(maxMonths - minMonths >= 6){
        a.push(c);
    }
  }
  return a;
}, []);

console.log(periods)

reduce等于colval的两个连续对象出现或者当前对象的0等于colval时,第一个0会创建一个新句点。在当前时期已经存在这样一个对象。

第二次减少仅保留大于或等于6个月的时段。

你可能想要简化第一个if中的reduce语句,我可能会让它变得更加复杂。

答案 1 :(得分:0)

let values = [
   { "year": 1960, "month": 1,  "colval": 1 },
   { "year": 1960, "month": 2,  "colval": 1 },
   { "year": 1960, "month": 3,  "colval": 2 },
   { "year": 1960, "month": 4,  "colval": 0 },
   { "year": 1960, "month": 5,  "colval": 2 },
   { "year": 1960, "month": 6,  "colval": 3 },
   { "year": 1960, "month": 7,  "colval": 0 },
   { "year": 1960, "month": 8,  "colval": 0 },
   { "year": 1960, "month": 9,  "colval": 2 },
   { "year": 1960, "month": 10, "colval": 3 },
   { "year": 1960, "month": 11, "colval": 1 },
   { "year": 1960, "month": 12, "colval": 2 },
   { "year": 1961, "month": 1,  "colval": 1 },
   { "year": 1961, "month": 2,  "colval": 3 },
   { "year": 1961, "month": 3,  "colval": 0 },
   { "year": 1961, "month": 4,  "colval": 1 },
   { "year": 1961, "month": 5,  "colval": 0 }
 ]

function getPeriods(months) {
  let periods = []; // this is an array of periods
  let prevInPeriod = false;
  let currPeriod;
  let zeros = 0;

  months.forEach(function (month) {
    let currIsZero = (month.colval === 0);
    let currInPeriod = !currIsZero || !zeros;
    if (!prevInPeriod && currIsZero) {
      currInPeriod = false;
    }

    if (!month.colval) {
      zeros++;
    }

    if (!prevInPeriod && !currInPeriod) {
      return;
    }

    if (!prevInPeriod && currInPeriod) { // entering period
      currPeriod = [month]; // creating new period with date
    } else if (prevInPeriod && currInPeriod) { // still in period
      currPeriod.push(month); // pushing new values
    } else if (prevInPeriod && !currInPeriod) { // period ends
      periods.push(currPeriod); // saving current period into results
      zeros = 0;
    }

    prevInPeriod = currInPeriod;
  });

  // checking the last period if it's in a results
  if (periods[periods.length - 1] !== currPeriod) {
    periods.push(currPeriod);
  }

  // filtering out periods which are shorter than 6
  periods = periods.filter(period => period.length >= 6);

  return periods;
}

这里有jsfiddle测试:https://jsfiddle.net/7awg75rh/1/

  1. 在上面的代码中,我遍历数组中的所有月份
  2. 将上个月与当前月份进行比较
  3. 每次迭代可能有四种状态:不在句号在句号离开句号进入句号
  4. 在每个场景中,我都会采取不同的行动。要么,什么都不做,在当前时期添加月份,创建当前月份或储蓄期的新期间
  5. 最后,我会过滤掉短于6的句号。