user7400006
user7400006

Reputation: 117

How to sort an array of odd numbers in ascending order, but keep even numbers at their position?

I want to sort only odd numbers without moving even numbers. For example, when I write :

sortArray([5, 3, 2, 8, 1, 4])

The expected result is :

[1, 3, 2, 8, 5, 4]

I am new to JavaScript and I came across a challenge on the Internet that has me perplexed. I normally wouldn't post asking for a solution on the Internet, BUT I have tried for hours and I would like to learn this concept in JavaScript.

The challenge states :

You have an array of numbers. Your task is to sort ascending odd numbers but even numbers must be on their places. Zero isn't an odd number and you don't need to move it. If you have an empty array, you need to return it.

Here is my code so far, please take it easy on me I am in the beginning stages of programming.

function sortArray(array) {
  let oddNums = [];
  for(let i = 0; i < array.length; i++) {
    if(array[i] % 2 !== 0) {
      oddNums.push(array[i]);
    }
  }
  oddNums = oddNums.sort((a,b)=> a-b);
  array.concat(oddNums);
  array = array.sort((a,b) => a-b);
  return array;
}

Upvotes: 5

Views: 25354

Answers (7)

hesam.mobham
hesam.mobham

Reputation: 1

def sort_array(source_array):
b = sorted([n for n in source_array if  n % 2 != 0])
c = -1
d = []
for i in source_array:
    c = c+1
    if i % 2 != 0 :
        d.append(c)
for x in range (len(d)):
    z = d[x]
    source_array[z] = b[x]
return source_array

Upvotes: -1

user1636522
user1636522

Reputation:

Here is a possible solution using a slightly customized selection sort :

var xs = [5, 3, 2, 8, 1, 4];

console.log(sortOddsOnly(xs));

function sortOddsOnly (xs) {
  var n = xs.length;
  for (var i = 0; i < n - 1; i++) {
    if (xs[i] % 2 === 1) {
      for (var j = i + 1; j < n; j++) {
        if (xs[j] % 2 === 1) {
          if (xs[i] > xs[j]) {
            var min = xs[j];
            xs[j] = xs[i];
            xs[i] = min;
          }
        }
      }
    }
  }
  return xs;
}

The first two if guarantee that we swap only odd numbers (x % 2 === 1 means "x is odd").

Upvotes: 0

Nina Scholz
Nina Scholz

Reputation: 386650

You could take a helper array for the odd indices and another for the odd numbers, sort them and apply them back on the previously stored indices of the original array.

var array = [5, 3, 2, 8, 1, 4],
    indices = [];

array
    .filter((v, i) => v % 2 && indices.push(i))
    .sort((a, b) => a - b)
    .forEach((v, i) => array[indices[i]] = v);

console.log(array);

Upvotes: 10

CRice
CRice

Reputation: 32176

Here's a solution using mostly the built-in array methods. Get a list of just the odds, sort it, then map through the original, replacing each item with the first sorted odd if the item is odd, or itself if even:

const array = [5, 3, 2, 8, 1, 4] // to: [1, 3, 2, 8, 5, 4]

function sortOddsOnly(arr) {
    const odds = arr
        .filter(x => x%2)
        .sort((a, b) => a - b);
        
    return arr
        .map(x => x%2 ? odds.shift() : x);
}

console.log(sortOddsOnly(array));

Upvotes: 8

yajiv
yajiv

Reputation: 2941

One of the possible solutions is this. What I have done is created new array odd(array with odd position in original array using Array.prototype.filter) and then sort that array using Array.prototype.sort. Then using Array.prototype.map change value of all odd element of original array with odd array.

x1=[5, 3, 2, 8, 1, 4];
function sortArray(array) {
  var odd = array.filter((x,i) => (i+1) % 2 ).sort((a,b) => a > b); //sort odd position and store that in new array
  return array.map((x,i) => (i+1) % 2 ? odd.shift() : x ); //if i is odd then replace it with element from 
                                                  //odd array otherwise keep the element as it is
}
console.log(sortArray(x1));

Upvotes: 0

FisNaN
FisNaN

Reputation: 2865

I have a solution like this.
Build a sorted odd number array 1st, and then fill the rest of even numbers in order:

const arr = [5, 3, 2, 8, 1, 4];

const odd = arr.filter(i => i%2 !== 0).sort();
let i = 0,
  result = [];
arr.forEach(e => {
  if (e%2 === 0) {
    result.push(e)
  } else {
    result.push(odd[i]);
    i++;
  }
});

console.log(result);

Upvotes: 4

Jonas Wilms
Jonas Wilms

Reputation: 138367

just do:

arr.sort((a, b) => a%2 && b%2 ? a - b : 0)

If that works depends on the sort algorithm your browser uses. A browserindependent version:

for(const [i1, v1] of arr.entries())
  for(const [i2, v2] of arr.entries())
    if( v1%2 && v2%2 && (i1 < i2) === (v1 > v2))
        ([arr[i1], arr[i2]] = [v2, v1]);

Upvotes: 0

Related Questions