Javascript - compare boolean arrays and creating a new one - javascript

I'm curious how I could compare these array's, bare in mind this is an example, it's not limited to 4 array's, as this could be more or less depending on user selection)
let array0 = [false,true,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,true ,true ,false,false,false,false,false,false,false,false,true ,true ,true ,true,true,false,true,true,true,true,false,false]
let array1 = [true ,true,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,true ,true ,true ,true ,false,true ,false,true ,true ,false,true ,true ,true ,true ,true,true,true ,true,true,true,true,true ,true ]
let array2 = [true ,true,true ,true ,true ,true ,true ,true ,true,true ,true ,true ,true ,true ,true ,true ,true ,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,true ,true,true,true,true,true ,true ]
let array3 = [true ,true,true ,true ,true ,true ,true ,true ,true,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true,true,true ,true,true,true,true,true ,true ]
The end goal is to get a new array with a true or false value based on comparison/validation of all of the above array's, a true value should only be set if all 4 array's have a true value in that index position, and a false if of them or not for example:
Array
result
Array
result
Array
result
array0[0]
false
array0[1]
true
array0[2]
false
array1[0]
true
array1[1]
true
array1[2]
false
array2[0]
true
array2[1]
true
array2[2]
true
array3[0]
true
array3[1]
true
array3[2]
false
result
false
true
false
let resultArray = [false, true, false, false, /* etc */]
Hope I have explained this correctly.

You could transpose the array and map all items having truthy values.
const
array0 = [false, true, false, true, true],
array1 = [true, true, false, false, true],
array2 = [false, true, true, false, true],
array3 = [true, true, true, true, true],
transpose = (r, a) => a.map((v, i) => [...(r[i] || []), v]),
result = [array0, array1, array2, array3]
.reduce(transpose, [])
.map(a => a.every(Boolean))
console.log(result);

I think you should create an array containing all your arrays. Then you will probably need a double for loop to calculate individual values. Check the nth index for every array and compute the value, where i is from 0 to the length of array (Basically, do the check for all the indices). You should get your computed result. Below is using only 2 arrays:
let array0 = [false,true,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,true,true,true,true,true,false,true,true,true,true,false,false]
let array1 = [true,true,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,true,true,true,true,false,true,false,true,true,false,true,true,true,true,true,true,true,true,true,true,true,true,true]
let newArr = [array0,array1];
let ans = [];
for(let i = 0 ; i < array1.length; i++){
let val = true;
for(let j = 0 ;j < newArr.length; j++){
val = val && newArr[j][i];
if(!val) break;
}
ans.push(val);
}
console.log(ans);

let array0 = [false, true, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, true, true, false, false, false, false, false, false, false, false, true, true, true, true, true, false, true, true, true, true, false, false]
let array1 = [true, true, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, true, true, true, true, false, true, false, true, true, false, true, true, true, true, true, true, true, true, true, true, true, true, true]
let array2 = [true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, true, true, true, true, true, true, true]
let array3 = [true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true]
let MAX_INDEX = Math.max(array0.length, array1.length, array2.length, array3.length)
let result = []
for (let i = 0; i < MAX_INDEX; i++) {
result[i] = array0[i] || false &&
array1[i] || false &&
array2[i] || false &&
array3[i] || false
}
console.log(result)

Since all your arrays have same length I guess you could simply do that:
let array0 = [false, true, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, true, true, false, false, false, false, false, false, false, false, true, true, true, true, true, false, true, true, true, true, false, false]
let array1 = [true, true, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, true, true, true, true, false, true, false, true, true, false, true, true, true, true, true, true, true, true, true, true, true, true, true]
let array2 = [true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, true, true, true, true, true, true, true]
let array3 = [true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true]
let result = Array.from({
length: array0.length
}).map((_, i) => array0[i] && array1[i] && array2[i] && array3[i])
console.log(result)

Related

Regex validation to match urls

I have this regex
/[-a-zA-Z0-9#:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}([a-zA-Z0-9#%._~#?={}]+-*[a-zA-Z0-9#%._~#=\/;]+)+.(?!-)[a-z]{2,24}\b((?:\{[^{}]*}|[-a-zA-Z0-9#%_+.~?&#\/=:$\[\]])*)$/
Which I want to match with these urls to true since I'm getting false with my current regex:
"ftp://user#host.com:80/abc/": true
"ftp://host.com": true
"http://abcewe.com": true
"https://abcewe.com": true
"mailto:someone#example.com": true
"news:newsgroup-name": true
"telnet://user:password#host:100": true
"http://ab-c.com": true
What do I need to add to match these urls?
Thank you very much for the help.
Note: I need the other codes so I cant remove them.
Note: Here is the full urls that I need to match. The rest aside above is already match with this regex, the above urls isnt.
{
"http://goog": false,
"http://googl": false,
"http://google": false,
"https://www.domains.com/#home": true,
"https://www.domains.com/{firstname}_{lastname}": true,
"https://www.domains.com/file[3].html": true,
"https://www.domains.com/?name=fred;age=50": true,
"https://www.domains.com/{name{age}}": false,
"https://www.domains.com/?name=fred;": false,
"http://www.google.com": true,
"https://www.amazon.com": true,
"http://joe:secret#www.liquidcrystalstudios.co.cc:8080/abc/": true,
"http://www.abcde.com:80/abc/": true,
"ftp://user#host.com:80/abc/": true,
"http://www.abcde.com/abc/": true,
"http://www.abcde.com/": true,
"http://joe:secret#www.liquidcrystalstudios.co.cc": true,
"http://jocce:seccccret#www.liquidcrystalstudios.co.cc": true,
"ftp://:abc#host.com/": false,
"ftp://foo:#host.com/": false,
"ftp://host.com": true,
"http://abcde.com": true,
"https://abcde.com": true,
"gopher://gopher.meulie.net/": true,
"mailto:someone#example.com": true,
"news:newsgroup-name": true,
"nntp://wild.server.example/example.group.n%2Fa/12345": true,
"telnet://user:password#host:100": true,
"wais://100.64.0.0:5": true,
"file://vms.host.edu/disk$user/my/notes/note12345.txt": true,
"prospero://host.dom//pros/name": true,
"abc://a.com": false,
"://abc.com": false,
"http//abc.com": false,
"http:abc.com": false,
"HTTP://www.ABCDW.com/ABC/": true,
"http://www.亜蔭.com/亜蔭/": false,
"http://www.弌傲僉.com/弌傲僉": false,
"http://www.俱咡.com/俱咡": false,
"http://www.丂㒒儈.com/丂㒒儈": false,
"http://www.亜腕弌.com/亜腕弌": false,
"http://www.アバ.com/ショアバ": false,
"http://www.アバショ.com/ジウンカ": false,
"http://174.129.0.77": true,
"http://174.1a.a.77": false,
"http://174.10.23.0": false,
"http://0.10.23.7": false,
"http://174.10.23.+7": false,
"http://-174.10.23.7": false,
"http://17-4.10.23.5": false,
"http://1.0.0.1": true,
"http://126.255.255.254": true,
"http://100.25.36.14": true,
"http://128.0.0.1": true,
"http://191.255.255.254": true,
"http://150.25.36.14": true,
"http://192.0.0.1": true,
"http://223.255.255.254": true,
"http://200.25.36.14": true,
"http://10.0.0.0": false,
"http://10.1.2.3": true,
"http://10.255.255.255": true,
"http://172.16.0.0": false,
"http://172.0.0.5": true,
"http://172.31.255.255": true,
"http://192.168.0.0": false,
"http://192.168.4.4": true,
"http://192.168.255.255": true,
"http://126.255.255.255": true,
"http://127.0.36.14": true,
"http://127.112.0.1": true,
"http://10.190.201.10:0?port=0": false,
"http://10.190.201.10:1?port=1": true,
"http://10.190.201.10:21?port=21": true,
"http://10.190.201.10:80?port=80": true,
"https://10.190.201.10:443?port=443": true,
"http://10.190.201.10:65535?port=65535": true,
"http://10.190.201.10:65535?port=65536": false,
"http://gooo.gl/09GxbZc": true,
"www.abc.com/miss-scheme": false,
"http&://10.190.201.10/wrong-scheme": false,
"http://test#url/wrong-hostname": false,
"http://FE80:0000:0000:0000:0202:B3FF:FE1E:8329/hostname-ipv6": false,
"http://10.190.201.10:10/path/1": false,
"HTTP://www.ABC①㌔№∮.com/①㌔№∮C/": false,
" http://🙂 😁 😆": false,
" http://zzz": false,
" :// . . ": false,
"https :// www. amazon. com": false,
"ht tps://ww w.am azon.co m": false,
"https://www.amazon.com ": false,
"https:// www. amazon. com ": false,
"htt ps://ww w.ama zon.c om ": false,
"https ://www .amazon .com ": false,
" https:// www. amazon. com": false,
"http://-abc.com": false,
"http://abc-.com": false,
"http://ab-c.com": true,
"http://.abc.com": false,
"http://abc..com": false,
"http://ab.c.com": true,
"http://+abc.com": false,
"http://ab+c.com": false,
"http://abc+.com": false,
"http://www.356.com": true,
"http://www.35accd6.com": true,
" http:/abc.com/acb": false,
"http:/abc.com/acb ": false,
"http:/a bc.com/a cb": false,
"http://a.c": false,
"http://.com": false,
"http://www.com": false
}

how to check first 3 or 4 elements are true in nodeJS?

time : [
true, true, true,
true, true, true,
true, false, false
]
this is an array I'm getting, I want to find with if condition whether first for elements are true or not?
Just slice and check then. (you can use Array.prototype.every for the checking)
const time = [
true, true, true,
true, true, true,
true, false, false
]
console.log(time.slice(0, 4).every(item => item))
This is a really simple task using the slice and includes method. First slice the list, then check to see if it includes any false values.
let firstFourAreTrue = !time
.slice(0, 4)
.includes(false);
In the description of the question time I think it is an object.
This code returns values for 3 and 4. The values are set in an array and other values can be added.
var t = {
time: [
true, true, true,
true, true, true,
true, false, false
]
};
var p = [3, 4];
p.forEach(i => {
var ret = t.time.slice(0, i).every(x => x);
console.log('First',i, ret);
});
A solution without slicing.
const check = array => array.every((v, i) => i >= 4 || v);
console.log(check([true, true, true, true, true, true, true, false, false]));
console.log(check([false, true, true, true, true, true, true, false, false]));
console.log(check([true, false, true, true, true, true, true, false, false]));
console.log(check([true, true, false, true, true, true, true, false, false]));
console.log(check([true, true, true, false, true, true, true, false, false]));

Based on elements value the left over element in the array of object should be modified

I have array of objects where if I have 4 objects in that if 3 element values are false then the remaining one object should also get false and vice versa.
If 5 elements 3 false 2 true, then no change in the o/p, if only one element is different from other then the value should modify.
Below is the array:
array = [{
"19714": false,
"19787": true,
"19870": false,
},
{
"19716": false,
"19797": false,
"19890": false,
"19891": true,
"19892": false,
"19894": false,
},
{
"16789": false,
"19785": false,
"19800": false,
"19370": false,
"19470": true,
"19874": false,
},
];
Here in the array the 1st object contains 3 elements in that there are two elements are false and the element which is true should also get false.
Same in second object all elements are false except one value
Below is the O/p:
array = [{
"19714": false,
"19787": false,
"19870": false,
},
{
"19716": false,
"19797": false,
"19890": false,
"19891": false,
"19892": false,
"19894": false,
},
{
"16789": false,
"19785": false,
"19800": false,
"19370": false,
"19470": false,
"19874": false,
},
];
How can I do that?
If false values are greater than true values then it will return all value as false and if true values are greater than false values then it will return all value as true and if both true and false values are same then there will be no change.
Try this.
var array = [{
"19714": false,
"19787": true,
"19870": false,
},
{
"19716": false,
"19797": false,
"19890": true,
"19891": true,
"19892": false,
"19894": false,
},
{
"16789": false,
"19785": false,
"19800": false,
"19370": false,
"19470": true,
"19874": false,
},
{
"19714": false,
"19787": true,
"19870": false,
"19788": true,
}
];
var output = array.map(x => {
var valuesLength = Object.values(x).length;
var trueIds = Object.keys(x).filter(key => x[key]);
var falseIds = Object.keys(x).filter(key => !x[key]);
if (trueIds.length !== falseIds.length && (trueIds.length===valuesLength-1 || falseIds.length===valuesLength-1)) {
var finalValue = trueIds.length > falseIds.length ? true : false;
Object.keys(x).forEach(key => x[key] = finalValue);
}
return x;
});
console.log(output);
You can use code like below. Here Object.entries(a) will return array of [key, value] pairs from object. Then filter it with true/false values and if length == 1 then update respective value with a[trueValues[0][0]] = false.
array.forEach(a => {
let trueValues = Object.entries(a).filter(e => e[1] === true);
let falseValues = Object.entries(a).filter(e => e[1] === false);
if (trueValues.length == 1) {
a[trueValues[0][0]] = false;
} else if (falseValues.length == 1) {
a[falseValues[0][0]] = true;
}
});
Try it below.
let array = [{
"19714": false,
"19787": true,
"19870": false,
},
{
"19716": false,
"19797": true,
"19890": true,
"19891": true,
"19892": true,
"19894": true,
},
{
"16789": false,
"19370": true,
"19470": true,
"19785": false,
"19800": true
}
];
array.forEach(a => {
let trueValues = Object.entries(a).filter(e => e[1] === true);
let falseValues = Object.entries(a).filter(e => e[1] === false);
if (trueValues.length == 1) {
a[trueValues[0][0]] = false;
} else if (falseValues.length == 1) {
a[falseValues[0][0]] = true;
}
});
console.log(array);
var array = [{
"19714": false,
"19787": true,
"19870": false,
},
{
"19716": false,
"19797": false,
"19890": false,
"19891": true,
"19892": false,
"19894": false,
},
{
"16789": false,
"19785": false,
"19800": false,
"19370": false,
"19470": true,
"19874": false,
},
{
"16789": true,
"19785": true,
"19800": false,
"19370": true,
"19470": true,
"19874": true,
},
{
"19714": false,
"19787": true,
"19870": false,
"19788": true,
},
{
"19714": false,
"19787": true,
}
];
let values = [];
let trueCount = 0;
let falseCount = 0;
let totalArrayCount = 0
array.forEach((item) => {
values = Object.values(item);
totalArrayCount = values.length
// get true's count
trueCount = values.filter((v) => {
return v == true;
}).length;
// get false's count
falseCount = values.filter((v) => {
return v == false;
}).length;
// If one of the boolean value count is 1 and object has more than two key-value pairs then only update the object
if (trueCount === 1 && totalArrayCount > 2) {
item = updateObject(item, false);
} else if (falseCount === 1 && totalArrayCount > 2) {
item = updateObject(item, true);
}
});
function updateObject(obj, boolVal) {
for (let key in obj) {
obj[key] = boolVal;
}
}
console.log(array)

Loop through array and draw * when value is true

I have an array with values true and false. I want to check if a value of an array is true draw '*'. And each row should move 1 position left.
Expected result ->
'*****
*****
*****
*****
*****'
I tried this way.
let points = [
[true, false, true, false, true, false, true, false, true, false],
[false, true, false, true, false, true, false, true, false, true],
[true, false, true, false, true, false, true, false, true, false],
[false, true, false, true, false, true, false, true, false, true],
[true, false, true, false, true, false, true, false, true, false]
];
let m = 10;
let n = 5;
let board = "";
let space = '\xa0';
for(let i = 0; i < points.length; ++i) {
for(let j = 0; j < points[i].length; ++j) {
if(points[i][j]) {
for (let y = 0; y < points[i]; y++) {
if(y > 0) {
board += space + "*";
space += space;
}
for (let x = 0; x < points[i][j]; x++) {
board += "*";
}
board += "\n";
}
}
return '';
}
}
You can use a couple reduce() functions to print the outer and inner loop using the index to control the initial spaces. The outer reduce iterates over each row and the inner reduce makes the * strings based on the boolean values.
let points = [
[true, false, true, false, true, false, true, false, true, false],
[false, true, false, true, false, true, false, true, false, true],
[true, false, true, false, true, false, true, false, true, false],
[false, true, false, true, false, true, false, true, false, true],
[true, false, true, false, true, false, true, false, true, false]
];
let result = points.reduce((str, arr, i) => {
return str
+ ' '.repeat(i)
+ arr.reduce((subst, bool) => subst + (bool ? '*' : ''), '')
+ '\n'
}, '')
console.log(result)
points
.map((row, i) => " ".repeat(i) + row.map(cell => (cell ? "*" : " ")).join(""))
.join("\n");
Based on your description, and if you want to stick to loops, the loop should be similar to this.
let points = [
[true, false, true, false, true, false, true, false, true, false],
[false, true, false, true, false, true, false, true, false, true],
[true, false, true, false, true, false, true, false, true, false],
[false, true, false, true, false, true, false, true, false, true],
[true, false, true, false, true, false, true, false, true, false]
];
let board = "";
for (let i = 0; i < points.length; i++) {
for (let j = 0; j < points[i].length; j++) {
if (j === 0 && i !== 0) {
board += "<br>";
for (let k = 0; k < i; k++) {
board += "\xa0";
}
}
board += points[i][j] ? "*" : " ";
}
}
document.write(board);
However if you want the "expected result" that you showed, you need to remove the adding of spaces. Your expected result doesn't match the description in this regard.
I would just use Array.prototype.map. The code here is using contemporary ES6 for brevity but could easily be ported to ES5 if need be.
let points = [
[true, false, true, false, true, false, true, false, true, false],
[false, true, false, true, false, true, false, true, false, true],
[true, false, true, false, true, false, true, false, true, false],
[false, true, false, true, false, true, false, true, false, true],
[true, false, true, false, true, false, true, false, true, false]
];
points.map((row, i) => {
const padded = [];
while (i--) {
padded.push(' ');
}
return [
...padded,
...row.map(point => point ? '*' : ' ')
].join('');
}).join('\n');
I'm using:
the spread operator to spread the padded and points array items into a new array which is then just joined into a string
arrow functions () => {} and an implicit return statement as the callback functions to map
Outputs

Javascript sort array of objects by a boolean property

See edit at end for actual problem.
Ok, I have this scenario:
a = [false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]
Then if I do this:
a.sort(function(a,b){return !a && b});
It gives me this:
[false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]
It's sorta doing a sort... but not quite... :(
How do I sort this array?
EDIT:
If you are wondering why I did not use just a.sort() is because my actual array is of objects, not a plain array like the one I posted. The real one has elements that look like [{xx:true},{xx:false},...]
a = [false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false];
a.sort(function(x, y) {
// true values first
return (x === y)? 0 : x? -1 : 1;
// false values first
// return (x === y)? 0 : x? 1 : -1;
});
console.log(a);
You must return 0 when a and b both have the same value, -1 if a is true and 1 otherwise.
To prevent implicit type conversion (which languages like TypeScript don't like), you can use Number() to explicitly convert the boolean to a number:
a = [false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false];
a.sort(function(x, y) {
return Number(x) - Number(y);
});
console.log(a);
Or using arrow functions:
a = [false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false];
a.sort((x, y) => Number(x) - Number(y));
console.log(a);
a simpler way:
a = [{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false}];
a.sort(function(a,b){return a.xx-b.xx});
console.log(a);
you can call a.reverse() after the sort() if you want it sorted the other way..
EDIT:
edited to reflect updated question of sorting an array of objects instead of an array of booleans.
An array does not have any equal positions, so why not leave away the equals check, and always return either -1 or 1. This approach works well with TS.
a.sort(x => x ? -1 : 1)
Note: I am a bit concerned how this affects internals of the sort function, but it seems to do the trick.
If you want to reverse sort
a.sort(x => !x ? -1 : 1)
Simple solution:
[true, false, true, false].sort((a, b) => b - a)
console.log([true, false, true, false].sort((a, b) => b - a));
PFB the solution worked for me in Typescript Angular 2 as well,
let a = [{aa:"1",xx:true},{aa:"10",xx:false},{aa:"2",xx:true},{aa:"11",xx:false},{aa:"3",xx:true},{aa:"12",xx:false},{aa:"4",xx:true},{aa:"13",xx:false},{aa:"5",xx:true},{aa:"14",xx:false},{aa:"6",xx:true},{aa:"15",xx:false},{aa:"7",xx:true},{aa:"16",xx:false},{aa:"8",xx:true},{aa:"17",xx:false},{aa:"9",xx:true},{aa:"18",xx:false}];
//a.sort(function(a,b){return a.xx-b.xx});
a.sort(function (x, y) {
// true values first
return (x.xx === y.xx) ? 0 : x ? -1 : 1;
// false values first
// return (x === y)? 0 : x? 1 : -1;
});
return JSON.stringify(a);
I also ran into this issue, here is my part, I hope it helps:
orders.sort((x, y) => {
if (x === y) return 0;
if (x) return -1;
return 1;
});
I wanted to see if I could do it without using the ? : operator, just for fun.
Note
This works on all sortable data types (strings, numbers), not just raw booleans. I'm not sure if this is faster than ? : and it's more convoluted. I just get sick of conditionals so it's just personal preference.
var b = [false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]
.sort((a,b) => Number(a > b) * 2 - 1);
I can turn that into a utility function and give it a meaningful name:
var sortOrder = {
asc: (a,b) => Number(a > b) * 2 - 1,
desc: (a,b) => Number(a < b) * 2 - 1
}
so then I can:
var b = [false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]
.sort(sortOrder.asc);
A pretty simple solution for the comparison function is to check if a < b, this gives 0 or 1 when converted to a number. We then want to map 0 to -1 and 1 to 1. To do that you can just multiply by 2 then subtract 1.
data.sort(function (a, b) {
return (a < b) * 2 - 1
}
or just
data.sort((a, b) => (a < b) * 2 - 1)
Problem sorted!
If any of your values are null they are treated as false (null*2 === 0) and any value that is undefined will become NaN (undefined*2 === NaN) which should make it last in either sort direction.
a=[true,false,true,false,true];
a.sort(function(x, y) {
a1=x?1:0
b1=y?1:0
return a1-b1
});
A boolean array with enough entries to represent all transitions i.e. true to true, true to false, false to false, false to true.
var boolarray = [true, false, true, true, false, false, true]
boolarray.sort( (a,b) => !(a ^ b) ? 0 : a ? -1 : 1)
The sort inverts the xor of the inputs. If the inputs are the same then return 0, if they are not then, if the 'a' input is true 'b' must be false so return -1, and vice versa return 1.
'a' and 'b' booleans are sorted when they differ and are ignored when
the same.
To use this method with objects just use the object member names for the sort arguments:
var objarray = [{xx:true}, {xx:false}, {xx:true}, {xx:true}, {xx:false}, {xx:false}, {xx:true}]
objarray.sort( (a,b) => !(a.xx ^ b.xx) ? 0 : a.xx ? -1 : 1)
You can actually just do like the following:
const sortedData = data.sort(
(a, b) => Number(b) - Number(a),
);
This solution is ok with Typescript has well since the conversion of boolean to number is explicit.
I got typescript errors on the return (x.xx === y.xx) ? 0 : x ? -1 : 1;
This is my solution when you want to sort on a boolean property
this.mediaList.sort( (a: MediaAutosubscriptionModel, b: MediaAutosubscriptionModel) => {
let status1: number = a.status === StatusEnum.ACTIVE ? 1 : 0;
let status2: number = b.status === StatusEnum.ACTIVE ? 1 : 0;
let comparison: number = 0;
let direction: number = this.sortDirection === SortDirectionsEnum.ASC ? -1 : 1;
if (status1 > status2) {
comparison = direction;
} else if (status1 < status2) {
comparison = -1 * direction;
}
return comparison;
});
Without using any ES6 function with time and space optimization -
const data = [false, true, true, true, false, false, false, true];
let lastElementUnchecked;
for(let i=0; i<data.length; i++){
if(data[i] && lastElementUnchecked !== undefined){
let temp = data[i];
data[i] = data[lastElementUnchecked];
data[lastElementUnchecked] = temp;
i = lastElementUnchecked;
lastElementUnchecked = undefined;
}else{
if(!data[i] && lastElementUnchecked === undefined){
lastElementUnchecked = i;
}
}
}
console.log(data)

Categories