3

I have an array with numbers.

var myArray = [1, 2, 3, 5, 8, 9, 10];

and I'd like to group them into a string with a from~to format until the next value is not continuous with the previous value, like the following example.

var outputArray = ["1~3", "5", "8~10"];

How to do that?

5
  • What have you tried yourself? Commented Dec 27, 2019 at 16:42
  • @ScottSauyet the self-answer Commented Dec 27, 2019 at 16:43
  • @VLAZ: Oh, missed that it was the same person. Commented Dec 27, 2019 at 16:55
  • @ScottSauyet Sorry for making you confused, I'm not a native speaker and don't know how to start a self-answer question, so I end it with How to do that sounds like I was begging for an answer. Commented Dec 28, 2019 at 5:08
  • @YamiOdymel: It's not a problem. It's fairly uncommon to see a self-answer like this, but there are other examples. I simply didn't notice. Commented Dec 29, 2019 at 2:43

5 Answers 5

4

You could take a slightly shorter approach by using the index to check if the first element needs an new array or if the value is not in order.

For the second mapping, you could just join all elements.

function group(numbers) {
    return numbers
        .reduce((result, value, index, array) => {
            if (!index || array[index - 1] + 1 !== value) {
                result.push([value]);
            } else {
                result[result.length - 1][1] = value;
            }
            return result;
        }, [])
        .map(array => array.join('~'));
}

console.log(group([1, 2, 3, 5, 8, 9, 10]));

Sign up to request clarification or add additional context in comments.

Comments

2

You can do this with Array.reduce() followed by Array.map():

const nums = [1, 2, 3, 5, 8, 9, 10]

const res = nums.reduce((acc, cur, idx, arr) => {
    if (idx === 0 || cur - 1 > arr[idx - 1]) {
        acc.push([cur])
    } else {
        acc[acc.length - 1].push(cur)
    }
    return acc
}, []).map(cur => cur.length > 1 ? cur.shift() + "~" + cur.pop() : cur[0])

console.log(res)

Comments

1

Go thru only one time all elements. Whenever there is pattern of numbers not in sequence, just put them in results array.

var myArray = [1, 2, 3, 5, 8, 9, 10];

let start = myArray[0];
let end = myArray[0];
const results = [];

for (let i = 1; i < myArray.length; i++) {
  if (myArray[i] === (end + 1)) {
    end = myArray[i];
  } else {
    results.push((start === end) ? `${start}` : `${start}~${end}`);
    start = myArray[i];
    end = myArray[i];
  }
}
results.push((start === end) ? `${start}` : `${start}~${end}`);

console.log(results);

Comments

0

Click here for CodePen (or a Chinese(中文)version).

Basically just create a lastValue variable, and iterating the array. If the currentValue - 1 equals the lastValue then it's a continuous number. Create a new group once the condition failed.

In the final you just merge the groups with a string.

var newArray = [];
var tempArray = []; 
var oldArray = [1, 2, 3, 5, 8, 9, 10];
var lastValue = null;

oldArray.forEach(value => {
  if (lastValue != value - 1 || lastValue === null) {
    tempArray.push([value, value]);
  } else {
    tempArray[tempArray.length - 1][1] = value;
  }
  lastValue = value;
});

tempArray.forEach(value => {
  if (value[0] === value[1]) {
    newArray.push(value[0].toString());
  } else {
    newArray.push(value.join("~"));
  }
});

// OUTPUS: (3) ["1~3", "5", "8~10"]
document.write(JSON.stringify(newArray));

Comments

0

For typescript, this function takes a sorted array of numbers and groups them into a single string.

function convertNumberArrayToRangeString(numbers: number[]): string {
    const delimiter = '~';
    return numbers
      .reduce((accumulator: string, currentValue: number, index: number, array: number[]) => {
        if (index > 0 && array[index - 1] + 1 !== currentValue) {
            if (index > 2 && array[index - 1] - array[index - 2] === 1) {
              accumulator +=  delimiter + array[index - 1].toString();
            }
            accumulator += ',' + currentValue.toString();
        } else if (index === 0 || index === array.length - 1) { // first or last
          if (array[index - 1] === currentValue - 1) {
            accumulator +=  delimiter;
          } else if (index > 0) {
            accumulator +=  ',';
          }
          accumulator += currentValue.toString();
        } 
        return accumulator;
      }, '');
  }

const list = [1, 2, 3, 6, 7, 8]; // sorted unique list
const groupedList = convertNumberArrayToRangeString(list);
console.log(groupedList);

Output> "1~3,6~8"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.