1

Help me write a function that will have the following results...

  • [1,5,9] => "1,5,9"

  • [1,2,3,5] => "1-3,5"

  • [1,2,5,6] => "1-2,5-6"

  • [1,2,3,7,8,10] => "1-3,7-8,10"

  • the array will always be in ascending order.

here is the code from my use case but all my variations print incorrect results.

var testArray = [{
    book: "Genesis",
    chapter: "1",
    verse: "1"
  },
  {
    book: "Genesis",
    chapter: "1",
    verse: "2"
  },
  {
    book: "Genesis",
    chapter: "1",
    verse: "3"
  },
  {
    book: "Genesis",
    chapter: "1",
    verse: "5"
  },
  {
    book: "Genesis",
    chapter: "1",
    verse: "10"
  },
  {
    book: "Genesis",
    chapter: "1",
    verse: "9"
  },
  {
    book: "Genesis",
    chapter: "1",
    verse: "17"
  },
  {
    book: "Genesis",
    chapter: "1",
    verse: "16"
  },
  {
    book: "Genesis",
    chapter: "1",
    verse: "18"
  },
];

function formatHandler() {
  //put the array in ascending order by verse
  const current = this.testArray.sort((a, b) => {
    return parseFloat(a.verse) - parseFloat(b.verse);
  });
  const shrtBk = current[0].book.slice(0, 3);
  let fmtdText = "";
  let i = 0;
  for (i = 0; i < current.length; i++) {
    const zero =
      typeof current[i - 1] === "undefined" ?
      Number(current[i].verse) :
      Number(current[i - 1].verse);
    const first = Number(current[i].verse);
    const second =
      typeof current[i + 1] === "undefined" ?
      -1 :
      Number(current[i + 1].verse);
    const third =
      typeof current[i + 2] === "undefined" ?
      -1 :
      Number(current[i + 2].verse);
    if (i === 0) {
      fmtdText += `${shrtBk} ${current[0].chapter}:${current[0].verse}`;
    } else if (
      second - first === 1 &&
      third - second === 1 /*&& second === not null*/
    ) {
      i++;
    } else if (
      second - first === 1 &&
      third - second !== 1 &&
      first - zero !== 1
    ) {
      fmtdText += `,${first}`;
    } else if (
      second - first === 1 &&
      third - second !== 1 /*&& second === not null*/
    ) {
      fmtdText += `-${second}`;
      i++;
    } else if (second - first !== 1) {
      fmtdText += `,${first}`;
    }
    console.log(fmtdText);
  }
}
formatHandler()

2 Answers 2

2

Ok, how about this

function formatWithRanges(ary) {
    let res = [],
        last = null

    for (let x of ary) {
        if (last && last[1] + 1 === x)
            last[1]++
        else
            res.push(last = [x, x])
    }

    return res
        .map(r => r[0] === r[1] ? r[0] : r[0] + '-' + r[1])
        .join(',')
}

console.log(formatWithRanges([1, 5, 9]))
console.log(formatWithRanges([1, 2, 3, 5]))
console.log(formatWithRanges([1, 2, 5, 6]))
console.log(formatWithRanges([1, 2, 3, 7, 8, 10]))

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

1 Comment

It seems to be working, I will implement it in a bit to see if I have any further questions!
0

Use .map() to modify the array and put a "-" or a "," depends on the following number. Then, take a substring to erase the last ",":

function range(a) {

  const s = a.map((e, i) => {
      if (e + 1 === a[i + 1]) {
         if (e - 1 !== a[i - 1]) 
           return e + "-";
      } else return e + ","; 
  }).join("");

  return s.substring(0, s.length - 1);
}

console.log(range([1, 5, 9]))
console.log(range([1, 2, 3, 5]))
console.log(range([1, 2, 5, 6]))
console.log(range([1, 2, 3, 7, 8, 10]))

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.