charlieyin
charlieyin

Reputation: 411

Unable to get array to display results of a nested for loop correctly

I'm trying to complete a codewars exercise in which you simply return a string of words in order based on the number in the string.

example:

order("is2 Thi1s T4est 3a") // should return "Thi1s is2 3a T4est"
order("4of Fo1r pe6ople g3ood th5e the2") // should return "Fo1r the2 g3ood 4of th5e pe6ople")

This is my attempt so far:

function order(words) {
  let wordsArr = words.split(' ')
  let result = [];
  for (let i = 0; i < wordsArr.length; i++) {
    for (let j = 0; j < wordsArr[i].length; j++) {
      if (typeof wordsArr[i][j] === 'number') {
        result[wordsArr[i][j]] = wordsArr[i]
      }
    }
  }
  return result
}

However this just returns an empty array. My logic is that I am looping through each letter of each word in wordsArr, and once the typeof letter matches 'number', then I set the results array index of wordsArr[i][j] equal to wordsArr[i]. This isn't working the way I'm expecting it to though, and I'm puzzled as to why!

Upvotes: 2

Views: 115

Answers (5)

StackSlave
StackSlave

Reputation: 10627

Looks like a good case for the use of sort:

function order(str){
  const r = str.split(/\s+/);
  r.sort((a,b)=>{
    let m1 = a.match(/\d+/) || [a], m2 = b.match(/\d+/) || [b];
    return m1[0]>m2[0];
  });
  return r;
}
console.log(order('is2 Thi1s T4est 3a'));
console.log(order('4of Fo1r pe6ople g3ood th5e the2'));
console.log(order('a zebra now just2 another1 test3 b'));

Upvotes: 1

Ala Eddine Menai
Ala Eddine Menai

Reputation: 2870

Maybe other solution in one line :

  • Split your array.
  • Use sort(comparable) to re-order elements.
  • Convert each word into an array
  • Check if there's a digit.
  • Compare these digits inside sort
  • Join the words ( Elements of an array )

  const order = str => str.split(" ").sort((a, b) => Array.from(a).find(e => 
  e.match(/\d/)) > Array.from(b).find(e => e.match(/\d/)) ? 1 : -1).join(" ")

  console.log(order("is2 Thi1s T4est 3a"))
  console.log(order("4of Fo1r pe6ople g3ood th5e the2"))

Upvotes: 1

richytong
richytong

Reputation: 2452

Here's an approach using a simple transformation.

const stripChars = word => word.replace(/[A-Za-z]+/g, '')

const xf = word => parseInt(stripChars(word), 10)

const order = words => words.split(' ').sort((a, b) => xf(a) - xf(b)).join(' ')

console.log(
  order('is2 Thi1s T4est 3a'),
)

console.log(
  order('4of Fo1r pe6ople g3ood th5e the2'),
)

Upvotes: 1

user12407908
user12407908

Reputation:

A more effective solution would be to use a regex to target the numeric character in each word, then convert the remaining number to an actual number.

const a = order("is2 Thi1s T4est 3a")
const b = order("4of Fo1r pe6ople g3ood th5e the2")

console.log(a, b)

function order(words) {
  return words.split(' ')
    .map(w => ({word:w, n:Number(/\d+/.exec(w)[0])}))
    .sort((a, b) => a.n - b.n)
    .map(o => o.word)
}

What this does is after splitting the string, it maps each word to an object containing the word and the number it contains, converted to an actual number. It then sorts the mapped array on that number, and finally maps back to just the array of words, which is returned.

It assumes each word will indeed have a number, so there's no check for null on the .exec of the regex.

Upvotes: 1

Nick
Nick

Reputation: 147166

wordsArr[i][j] is a character, regardless of whether it is numeric, so you need to check whether it is a digit or not, which you can do with a regex match against /\d/. If it is a digit, add the word to the result:

function order(words) {
  let wordsArr = words.split(' ')
  let result = [];
  for (let i = 0; i < wordsArr.length; i++) {
    for (let j = 0; j < wordsArr[i].length; j++) {
      if (wordsArr[i][j].match(/\d/)) {
        result[wordsArr[i][j]] = wordsArr[i]
      }
    }
  }
  return result.join(' ')
}

console.log(order("is2 Thi1s T4est 3a")) // should return "Thi1s is2 3a T4est"
console.log(order("4of Fo1r pe6ople g3ood th5e the2")) // should return "Fo1r the2 g3ood 4of th5e pe6ople")

Upvotes: 2

Related Questions