Reputation: 411
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
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
Reputation: 2870
Maybe other solution in one line :
sort(comparable)
to re-order elements.sort
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
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
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
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