Home > Enterprise >  Iterate over two separate arrays of different length and populate a third using a condition in JavaS
Iterate over two separate arrays of different length and populate a third using a condition in JavaS

Time:07-15

I've done something similar in the past with a nested loop, but for some reason I can't get my mind around this to get it to work. I keep running into problems that involve indexing of two separate arrays and it's been a continual stumbling block

In this case, I'm trying to sort a string. The string includes letters and numbers, the task is to sort the letters in reverse alphabetical order while keeping the numbers at their same index.

I've come up with this solution (probably not the most efficient), but can't get the sortString array to come together so that I can join the letters and numbers back into a string.

function reverse(str) {
    // split the str into an array
  const arr = [...str]
  // converts each element in arr to a number, letters are string 'NaN'
  const numArray = arr.map(x=> Number(x)).map(x=> x >= 0 ? x : String(x))
  // array of the sorted letters
  const letters = arr.filter(x=> !/[0-9]/g.test(x)).reverse()
    // initiate empty array to hold the combined numbers and letters
  let sortString = []
  // Use for loop to cycle through and replace elements that are 'NaN' with letters from the letter array.  All pushed to sortString.
  for (let i=0; i<arr.length; i  ) {
    sortString.push(numArray[i] === 'NaN' ? letters[0] : numArray[i])
  }
 return sortString
}


reverse("ab89c") // output should be "cb89a"

CodePudding user response:

You could get an array of non digits, sort it and map the splitted string with the sorted letters in places if not a digit.

const
    reverse = string => {
        const
            array = Array.from(string),
            letters = array
                .filter(v => /\D/.test(v))
                .sort();
            
        return array
            .map(v => /\D/.test(v) ? letters.pop() : v)
            .join('');
    };

console.log(reverse("ab89c"));

A slightly different approach takes a Proxy for the wanted items of sorting:

How to sort only part of array? between given indexes

CodePudding user response:

Here's code that works:

Explanation of how the code works is in-line as comments.

Basically it takes the numbers out, sorts the letters in reverse, and puts the sorted letters back in the right place.

Because it's step-by-step, you could add console log on each variable after it's assigned to see how it works step by step.

function reverse(input) {
    // This function from: https://stackoverflow.com/a/32567789/569302
    function testIsLetter(c) {
        return c.toLowerCase() != c.toUpperCase();
    }
    // Convert from array to string to process character by character
    let inputAsArray = input.split('');
    // This is where we'll lookup where to put the letters when we're done
    let mapped = inputAsArray.map((s) => {
        return {
            s,
            isLetter: testIsLetter(s)
        }
    })
    // Now that we've captured where the letters are, take the numbers (non-letters) out
    let filtered = mapped.filter(m => m.isLetter)
    // Convert the object into just letters so they're easily compared when we sort
    let filteredAsLettersArray = filtered.map(f => f.s)
    // Sort ascending
    filteredAsLettersArray.sort()
    // Reverse to sort descending
    filteredAsLettersArray.reverse()
    // Now we need to put the letters back.
    let resultAsArray = [];
    let letterIndex = 0;
    mapped.forEach(m => {
        // If it's a letter, we use the sorted result (incrementing letterIndex each time)
        if (m.isLetter) {
            resultAsArray.push(filteredAsLettersArray[letterIndex]);
            letterIndex  ;
        } else {
            // Otherwise we use the number
            resultAsArray.push(m.s);
        }
    });
    let result = resultAsArray.join('');

    return result;
}
console.log(reverse("ab89c"));
console.log(reverse("1a2eb8f9c"));
  • Related