最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

json - Javascript reduce() until sum of values < variable - Stack Overflow

programmeradmin5浏览0评论

I am fetching an array of video durations (in seconds) from a JSON file in Javascript, that, to simplify, would look like this:

array = [30, 30, 30]

I would like to add each value to the previous value until a condition is met (the sum being less than a variable x) and then to get both the new value and the index position in the array of the video to play.

For example if x=62 (condition), I would like the first two values in the array to be added (from my understanding reduce() is appropriate here), and the index = 2 (the second video in the array).

I've got the grasp of reduce():

var count = array.reduce(function(prev, curr, index) {
                    console.log(prev, curr, index);
                    return prev + curr;
                });

But can't seem to get beyond this point.. Thanks

I am fetching an array of video durations (in seconds) from a JSON file in Javascript, that, to simplify, would look like this:

array = [30, 30, 30]

I would like to add each value to the previous value until a condition is met (the sum being less than a variable x) and then to get both the new value and the index position in the array of the video to play.

For example if x=62 (condition), I would like the first two values in the array to be added (from my understanding reduce() is appropriate here), and the index = 2 (the second video in the array).

I've got the grasp of reduce():

var count = array.reduce(function(prev, curr, index) {
                    console.log(prev, curr, index);
                    return prev + curr;
                });

But can't seem to get beyond this point.. Thanks

Share Improve this question edited Mar 19, 2021 at 18:17 jinglesthula 4,5875 gold badges47 silver badges84 bronze badges asked Oct 27, 2016 at 19:10 ogotogot 3412 silver badges19 bronze badges 6
  • 1 why not use for loop? – jonzee Commented Oct 27, 2016 at 19:12
  • i agree about the for, since you need to break early and return 2 values (index and sum) – dandavis Commented Oct 27, 2016 at 19:13
  • 1 or a while loop would work. while(total < threshold && i < array.length) { total+= array[i]; i++;} – Mic Commented Oct 27, 2016 at 19:16
  • @Mic it wouldn't work if the first value > threshold – Utopik Commented May 26, 2017 at 10:42
  • @Utopik That's an awfully easy thing to check. Several of the actual answers will fail on the same case. – Mic Commented May 26, 2017 at 11:15
 |  Show 1 more ment

7 Answers 7

Reset to default 12

You could use Array#some, which breaks on a condition.

var array = [30, 30, 30],
    x = 62,
    index,
    sum = 0;
    
array.some(function (a, i) {
    index = i;
    if (sum + a > x) {
        return true;
    }
    sum += a;
});

console.log(index, sum);

With a pact result and this args

var array = [30, 30, 30],
    x = 62,
    result = { index: -1, sum: 0 };
    
array.some(function (a, i) {
    this.index = i;
    if (this.sum + a > x) {
        return true;
    }
    this.sum += a;
}, result);

console.log(result);

var a = [2,4,5,7,8];
var index;
var result = [0, 1, 2, 3].reduce(function(a, b,i) {
  var sum = a+b;
  if(sum<11){
    index=i;
    return sum;
  }
}, 2);
console.log(result,index);

What about using a for loop? This is hack-free:

function sumUntil(array, threshold) {
    let i
    let result = 0

    // we loop til the end of the array
    // or right before result > threshold
    for(i = 0; i < array.length && result+array[i] < threshold; i++) {
        result += array[i]
    }

    return {
        index: i - 1, // -1 because it is incremented at the end of the last loop
        result
    }
}

console.log(
    sumUntil( [30, 30, 30], 62 ) 
) 
// {index: 1, result: 60}

bonus: replace let with var and it works on IE5.5

You could do

    var limit = 60;
    var array = [30,30,30];
    var count = array.reduce(function(prev, curr, index) {
      var temp = prev.sum + curr;
      if (index != -1) {
        if (temp > limit) {
          prev.index = index;
        } else {
          prev.sum = temp;
        }
      }
      return prev;
    }, {
      sum: 0,
      index: -1
    });

    console.log(count);

What about this : https://jsfiddle/rtcgpgk2/1/

var count = 0; //starting index
var arrayToCheck = [20, 30, 40, 20, 50]; //array to check
var condition = 100; //condition to be more than
increment(arrayToCheck, count, condition); //call function

function increment(array, index, conditionalValue) {

  var total = 0; //total to add to
  for (var i = 0; i < index; i++) { //loop through array up to index
    total += array[i]; //add value of array at index to total
  }

  if (total < conditionalValue) { //if condition is not met
    count++; //increment index
    increment(arrayToCheck, count, condition); //call function

  } else { //otherwise
    console.log('Index : ', count) //log what index condition is met
  }

}
// define the max outside of the reduce
var max = 20;
var hitIndex;
var count = array.reduce(function(prev, curr, index) {
                let r = prev + curr;
                // if r is less than max keep adding 
                if (r < max) { 
                 return r 
                } else {
                  // if hitIndex is undefined set it to the current index
                  hitIndex = hitIndex === undefined ? index : hitIndex;
                  return prev;
                }
            });
console.log(count, hitIndex);

This will leave you with the index of the first addition that would exceed the max. You could try index - 1 for the first value that did not exceed it.

You can create a small utility method reduceWhile

// Javascript reduceWhile implementation
function reduceWhile(predicate, reducer, initValue, coll) {
    return coll.reduce(function(accumulator, val) {
        if (!predicate(accumulator, val)) return accumulator;
        return reducer(accumulator, val);
    }, initValue)
};

function predicate(accumulator, val) {
    return val < 6;
}

function reducer(accumulator, val) {
    return accumulator += val;
}

var result = reduceWhile(predicate, reducer, 0, [1, 2, 3, 4, 5, 6, 7])

console.log("result", result);
发布评论

评论列表(0)

  1. 暂无评论