2

i need to sort my array. I'd like to see string starting/containing numbers after alfa.

As:

['ip', 'email', '0email', 'em0ail' ,1001, '23name', 'name', 'address']

should be:

['address', 'email', 'em0ail', 'ip', 'name', '0email', 1001, '23name']

So 0 should be after z

columns.sort((a, b) => {
      const x = a.toString();
      const y = b.toString();
      if (x < y) {
        return -1;
      }
      if (x > y) {
        return 1;
      }
      return 0;
    });

returns numbers first

How should i approach this case? Do i have to iterate through whole string?

2
  • Split the original array in two arrays: startWithLetter and startWithNumber. Sort them individually and merge the arrays as you want. Commented Jul 2, 2019 at 11:24
  • @EliasSoares seems like too much work, rather than just checking the start of each item during sorting. Commented Jul 2, 2019 at 11:27

2 Answers 2

3

Do i have to iterate through whole string?

Not if you're just basing this on the first character in the string (as you seem to, with em0ail being sorted with the strings). Just check whether the strings start with a digit or a non-digit, and in cases where one has a digit but the other doesn't, return the appropriate 1 or -1 to put the non-digit one first; in cases where they both do or don't start with a digit, return the result of localeCompare.

(For the one that's a number, we can just convert to string.)

const columns = ['ip', 'email', '0email', 'em0ail' ,1001, '23name', 'name', 'address'];

function startsWithDigit(v) {
    const ch = v[0];
    return ch >= "0" && ch <= "9";
}

columns.sort((a, b) => {
    a = String(a);
    b = String(b);
    adigit = startsWithDigit(a);
    bdigit = startsWithDigit(b);
    if (adigit == bdigit) {
        return a.localeCompare(b);
    } else if (adigit) {
        return 1;
    } else {
        return -1;
    }
});

console.log(columns);

Sign up to request clarification or add additional context in comments.

4 Comments

An alternative for startsWithDigit implementation is to do a parseInt and check if the result is NaN. Started writing an answer where this was basically the only major difference but no need to now, so I'm leaving it as a comment.
@VLAZ - That would be simpler, wouldn't it? Good idea.
Hmm, I thought of a (potential) problem with parseInt - spaces at the start. The string " 123abc" will be parsed to 123. I don't know if OP expects that to be the case (space is ignored) or not.
That's fair enough. parseInt is a possible approach but without knowing the requirements here it's hard to say if it's correct. It does seem a bit inconsistent, though, since " a" and "b" would be sorted differently to " 1" and "2".
0

<!DOCTYPE html>
<html>
<head>

</head>

<body>


<script>
var columns=['ip', 'email', '0email', 'em0ail' ,1001, '23name', 'name', 'address'];
function Turn(CharZ){
	//Make 0~9 biger then a-z and A-Z
	if(CharZ<'9'.charCodeAt()){
		return CharZ+'Z'.charCodeAt();
	}
	return CharZ;
}
columns.sort((a, b) => {
	var x = a.toString();
	var y = b.toString();
	var Lx=x.length;
	var Ly=y.length;
	var MinL=Math.min(Lx, Ly);
	for (var i = 0; i < MinL; i++) {
		if(Turn(x.charCodeAt(i))-Turn(y.charCodeAt(i))>0){
			return 1;
		}else if(Turn(x.charCodeAt(i))-Turn(y.charCodeAt(i))<0){
			return -1;
		}
		
		
	}
	//if front all equals  but length not same mean there is remain
	if (Lx > Ly) {
		return 1;
	}
	if (Lx < Ly) {
		return -1;
	}
	return 0;
});
document.body.innerHTML = columns;

</script>

</body>
</html>

Hope this help

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.