Reputation: 45
My problem is that I am trying to iterate over an array several times, however, my for
loop will only iterate over the array once (Or so it seems to me) which causes the outcome to be wrong.
What I am trying to do is loop on this array: let arr = ["e5", "b2", "a1", "c3","d4"];
and grabbing the string based on its number to move it to the first, second, third... position in the array depending on that number.
My code does not throw any error, however, seems like it iterates only once, grabs "a1"
, moves it to position 0 in the array and that's it. It doesn't iterate again to grab b2 and move it to position 1 in the array.
Next I would like to show you my code:
function order(words) {
let sp = words.split(" "); // Array to split string
let pos = 1; //variable to store number 1 to find in string
let arr = []; //New array to push into, since trying to move values in same array wasn' tworking.
for (let i = 0; i < sp.length; i++) {
if (sp[i].includes(pos)) {
arr.push(sp[i]);
pos = pos + 1;
}
console.log(i);
}
return arr;
}
order("is2 Thi1s T4est 3a");
When I execute the above code, it returns:
0
1
2
3
[ 'Thi1s' ]
So as you can see, the result tells me that it iterates once, grabs "thi1s"
and pushes it to the new array, however, it stops at that point and doesn´t do the other iterations or the rest of the pushing.
I am logging i
to the console to see how many times it's iterating.
Link to the REPL: https://repl.it/@Otho01/Variables#index.js
Upvotes: 0
Views: 129
Reputation: 12637
The entire approach has flaws. Let's try order("is2 Thi123s T24est do9 3a")
. I'd expect the result to be
["is2", "3a", "do9", "Te4est", "Thi123s"]
but instead I get
["Thi123s", "is2", "Thi123s", "T24est", "Thi123s", "3a", "T24est"]
and do9
ain't even in the result.
Thi123s
matches for pos 1, 2 and 3
not pos 123
, that'S why you get duplicates, and you get them at the wrong places in the result.sp
so it can be matched again by a different pos, again that's why you get duplicates. And it means that you check the first elements over and over and over for every pos
123
, but if you did, you'd check the entire array for every number from 25
to 122
without pushing a single value to the returned result.This entire approach is incredibly expensive (for what it does) and would become even more so trying to fix it. So let's try a different approach; let's parse the number in the word and sort the array by that number.
const logCalls = [];
function getNumber(word){
logCalls.push(word);
return Number(word.match(/\d+/));
}
function order(words){
return words.split(" ").sort((a,b) => getNumber(a) - getNumber(b));
}
console.log(order("is2 Thi123s T24est do9 3a"));
console.log("getNumber calls:");
console.log(logCalls.join("\n"));
.as-console-wrapper{top:0;max-height:100%!important}
But as you can see, getNumber
is called quite a few times. And this list grows exponentially with the number of words you sort.
So let's improve on that and use String#matchAll to match all numbers only once and then sort:
function order(words){
// matchAll() returns an iterator. To sort that we first have to make this an array
const matches = [...words.matchAll(/\b[a-z]*(\d+)\w*\b/gi)];
console.log("matches", matches);
const sorted = matches.sort((a,b) => a[1] - b[1]);
console.log("sorted", sorted);
return sorted.map(match => match[0]);
// summary:
// return [...words.matchAll(/\b[a-z]*(\d+)\w*\b/gi)]
// .sort((a,b) => a[1] - b[1])
// .map(match => match[0])
}
console.log(order("is2 Thi123s T24est do9 3a"));
.as-console-wrapper{top:0;max-height:100%!important}
Luis, you seem quite new to programming in general, so here's a little
/\b[a-z]*(\d+)\w*\b/gi
)? MDN RegExp/\b[a-z]*(\d+)\w*\b/gi
: https://regex101.com/r/Zdt4BJ/1[...something]
? MDN spread syntaxname => something
? MDN arrow functionUpvotes: 0
Reputation: 36
I would also recommend looking into the array.sort() method as that might simplify your code Combine that with looking for the number within the string, and that should solve your issue
Array.sort() Find number in string
Upvotes: 0
Reputation: 769
The algorithm provided only loops the array of words once. For what you stated your goal is to find the position of each word based on a number inside each word. There are several ways of solving this but I will explain an easy algorithm.
You can accomplish the desired result by creating a loop over the positions {1..N}
and inside this loop another loop on the words {word1...wordN}
. So for each position you will try to find what word belongs to that position. The following algorithm is one of many solution for this problem:
function order(words){
let sp = words.split(" ");
let arr = [];
for (let pos = 1; pos <= sp.length; pos++) {
for (let i = 0; i < sp.length; i++) {
if (sp[i].includes(pos)) {
arr.push(sp[i])
}
}
}
return arr;
}
order("is2 Thi1s T4est 3a");
The result of this code is [ 'Thi1s', 'is2', '3a', 'T4est' ]
Upvotes: 1