Unexpected behaviour of Javascript Array.sort() - javascript

I've tried to sort an array of integers ascending.
For understanding the behaviour of the sort-method I've put a console.log in the callback-function:
var field = [50, 90, 1, 10, 2];
console.log(field.join(' | '));
var i = 0
field.sort(function(a, b) {
console.log(++i + 'a: ' + a + ', b: ' + b);
if (a === b) {
return 0;
} else if (a > b) {
return 1;
} else {
return -1;
}
});
console.log(field.join(' | '));
Result of the console.log:
PROTOKOLL: 50 | 90 | 1 | 10 | 2
PROTOKOLL: 1 a: 90, b: 50
PROTOKOLL: 2 a: 1, b: 90
PROTOKOLL: 3 a: 1, b: 50
PROTOKOLL: 4 a: 10, b: 90
PROTOKOLL: 5 a: 10, b: 50
PROTOKOLL: 6 a: 10, b: 1
PROTOKOLL: 7 a: 2, b: 90
PROTOKOLL: 8 a: 2, b: 10
PROTOKOLL: 9 a: 2, b: 1
PROTOKOLL: 1 | 2 | 10 | 50 | 90
After all I know about the Array.sort() method the result should be:
a: 50, b: 90
... but it's the other way.
Can anyone explain it?

It works like that.
Always take the second number and check if it in the right place:
Diagram:
1) 90 > 50 ----> No change
2) now check the second and third number 90 < 1 ---> 1 and 90 swap.
3) check if the first number is lesser than the new second number(1) - 50 < 1 - swap again 50 and 1.
4) 1 is the first number in the array, so go back to 90 and check the number after 90.
And it is continue like this. OK?

It's depends of implementation. In IE 11 you get output as:
50 | 90 | 1 | 10 | 2
1a: 90, b: 50
2a: 1, b: 90
3a: 1, b: 50
4a: 10, b: 90
5a: 10, b: 50
6a: 10, b: 1
7a: 2, b: 90
8a: 2, b: 10
9a: 2, b: 1
1 | 2 | 10 | 50 | 90
In Chrome you'll get:
50 | 90 | 1 | 10 | 2
1a: 50, b: 90
2a: 90, b: 1
3a: 50, b: 1
4a: 90, b: 10
5a: 50, b: 10
6a: 1, b: 10
7a: 90, b: 2
8a: 50, b: 2
9a: 10, b: 2
10a: 1, b: 2
1 | 2 | 10 | 50 | 90
But in Firefox you'll get:
50 | 90 | 1 | 10 | 2
1a: 50, b: 90
2a: 90, b: 1
3a: 50, b: 1
4a: 10, b: 2
5a: 90, b: 2
6a: 1, b: 2
7a: 50, b: 2
8a: 50, b: 10
1 | 2 | 10 | 50 | 90
Pay attention to number of steps. Final results are the same. The internal implementation is different.

Related

How do I obtain the array

I have an array of objects. Each object has an key of leftpixel. What I am trying to achieve is to obtain an array i.e. newArray with elements that are derived by subtracting leftpixel key value of first obj in array with second leftpixel key value that would make first element of newArray, second element would be obtained by subtracting leftpixel key value of second obj in array with third leftpixel key value.
The array that I have is like this
[
{
A: "FSDF"
B: "$145.0"
leftpixel: 2
},
{
A: "DFH"
B: "$463.0"
leftpixel: 191
},
{
A: "FDH"
B: "$546.0"
leftpixel: 191
},
{
A: "DSG"
B: "$154.0"
leftpixel: 192
}
]
The new Array that I want should be like this
newArray = [189, 0, 1]
You could slice the array and get the delta of the sliced array items and the original array at the same index,
var data = [{ A: "FSDF", B: "$145.0", leftpixel: 2 }, { A: "DFH", B: "$463.0", leftpixel: 191 }, { A: "FDH", B: "$546.0", leftpixel: 191 }, { A: "DSG", B: "$154.0", leftpixel: 192 }],
deltas = data.slice(1).map((v, i) => v.leftpixel - data[i].leftpixel);
console.log(deltas);
This is a slightly verbose implementation that also includes the first value which can be sliced/filtered out later.
let data = [{
A: "FSDF",
B: "$145.0",
leftpixel: 2
},
{
A: "DFH",
B: "$463.0",
leftpixel: 191
},
{
A: "FDH",
B: "$546.0",
leftpixel: 191
},
{
A: "DSG",
B: "$154.0",
leftpixel: 192
}
]
let result = data.map((item, index, arr) => {
if (index === 0) {
return item.leftpixel;
}
return item.leftpixel - arr[index - 1].leftpixel
})
console.log(result.slice(1))

How to join two dataframes in JS with data-forge?

I'm trying to use data-forge to join two dataframes, but I'm getting an empty merged dataframe:
const a = new DataFrame([{ A: 10, b: 1 }, { A: 20, b: 2 }, { A: 30, b: 3 }]);
const b = new DataFrame([{ A: 10, c:11 }, { A: 20, c:22 }, { A: 30, c:33 }]);
const ab = a.join(
b,
left => left.A,
right => right.A,
(left, right) => {
return { A: left.A, b: left.b, c: right.c };
}
);
// {content: null}
I believe your join is working as intended. I suspect the reason your are getting {content: null} is that your are console.logging ab, but due to data-forge's lazy evaluation, it hasn't resolved the content. If you use the .toString() method, it forces lazy evaluation to complete. Try this:
const a = new dataForge.DataFrame([
{ A: 10, b: 1 },
{ A: 20, b: 2 },
{ A: 30, b: 3 },
]);
const b = new dataForge.DataFrame([
{ A: 10, c: 11 },
{ A: 20, c: 22 },
{ A: 30, c: 33 },
]);
const ab = a.join(
b,
(left) => left.A,
(right) => right.A,
(left, right) => {
return { A: left.A, b: left.b, c: right.c };
},
);
console.log(ab);
// DataFrame { configFn: [Function], content: null }
console.log(ab.toString());
// __index__ A b c
// --------- -- - --
// 0 10 1 11
// 1 20 2 22
// 2 30 3 33

Javascript object map calculate the count of keys with values in a certain range

My problem is that I want to create a new object containing the count of keys with a values in a certain range . I think the best way for me to articulate this problem is by illustrating it as follows.
My dataset is as follows:
a = a sequence of ordered numbers from 1-1000 like an id/row number
b = any random number between 1-100
{"a":1,"b":59},
{"a":2,"b":88},
{"a":3,"b":69},
{"a":4,"b":28},
{"a":5,"b":75},
{"a":6,"b":78}
...]
Now I want to create an algorithm that calculates the number of a's (row numbers) with a frequency(b) in the range of e.g: 0-9 and put that value into a new object which would ideally look something like
with c representing that range(0-9, 1-19, 20-29...90-100)
and d representing the count of id's(a) with a frequency(b) in range(c)
[
{"c":1, "d":10},
{"c":2, "d":13},
{"c":3, "d":20},
...
{"c":10, "d":6}
]
I have tried a few different things without getting the desired result. I also need to put the result of that count into a new object Map which I am unsure how to do.
dat = [
{ "ruid": 1, "id_frequency": 5 },
{ "ruid": 2, "id_frequency": 88 },
{ "ruid": 3, "id_frequency": 69 },
{ "ruid": 4, "id_frequency": 28 },
{ "ruid": 5, "id_frequency": 75 },
{ "ruid": 6, "id_frequency": 78 },
{ "ruid": 7, "id_frequency": 18 },
{ "ruid": 8, "id_frequency": 90 },
{ "ruid": 9, "id_frequency": 22 }
];
var freq = Object.keys(dat).filter(function(key){
return ( dat[key] > 0 && dat[key] <10 );
}).length;
You could take an array and the integer value of a tenth of the value as index for counting.
var data = [{ a: 1, b: 59 }, { a: 2, b: 88 }, { a: 3, b: 69 }, { a: 4, b: 28 }, { a: 5, b: 75 }, { a: 6, b: 78 }],
result = data
.reduce((r, { b }) => {
r[Math.floor(b / 10)].d++;
return r;
}, Array.from({ length: 10 }, (_, i) => ({ c: i + 1, d: 0})))
console.log(result);

How to sort array by two linked fields? JS [duplicate]

This question already has answers here:
Javascript - Sort Array of objects by 2 Properties
(4 answers)
Closed 4 years ago.
There is a simple part of the code where I need to sort an array of objects by the next way (sorting array objects by a prop first and then by the b prop). So the result should look's like:
var a = [
{
a: 1,
b: 2
},
{
a: 1,
b: 4
},
{
a: 1,
b: 5
},
{
a: 2,
b: 1
},
{
a: 2,
b: 3
},
{
a: 2,
b: 4
}
]
But unfortunately, my code below doesn't seem to work well. Could someone help me? Thank you in advance.
var a = [
{
a: 2,
b: 4
},
{
a: 2,
b: 3
},
{
a: 1,
b: 2
},
{
a: 1,
b: 4
},
{
a: 1,
b: 5
},
{
a: 2,
b: 1
}
]
a.sort((first, second) => first.a - second.a && first.b - second.b ? 1 : -1)
console.log(a)
You need to check the first property a if they are equal then go for b.
const a = [{"a":2,"b":4},{"a":2,"b":3},{"a":1,"b":2},{"a":1,"b":4},{"a":1,"b":5},{"a":2,"b":1}];
a.sort((obj1 ,obj2) => obj1.a - obj2.a ? obj1.a - obj2.a : obj1.b -obj2.b );
console.log(a);

(Lodash) Is there a method to check if an identical object exists (nested) in a collection?

I was wondering if there is a Lodash approach to this problem, which I would otherwise solve with a for loop. I would like to return true if collection contains one or more elements with nested object identical to c.
The below example would return true because collection[1] contains an identical c.
Needle:
c = {
x: 11,
y: 22,
z: 33
}
Haystack:
collection = [
{
a: 1,
b: 1,
c: {
x: 10,
y: 20,
z: 30
},
d: 1
},
{
a: 1,
b: 1,
c: {
x: 11,
y: 22,
z: 33
},
d: 1
},
{
a: 1,
b: 1,
c: {
x: 12,
y: 24,
z: 36
},
d: 1
}
]
This is different from questions such as How to do a deep comparison between 2 objects with lodash? because I need to check if any of the collection items contain an identical object nested within them, not compare whether two objects are identical to each other.
Thanks in advance for your help.
You can use _.isEqual in a recursive function:
function find(h, n) {
if (_.isEqual(h, n)) return true;
let found;
if (Array.isArray(h)) {
for (let e of h) {
found = find(e, n);
if (found) return found;
}
} else if (h instanceof Object) {
return find(Object.values(h), n);
}
return false;
}
var c = {
x: 11,
y: 22,
z: 33
};
var d = {
x: 1111,
y: 2222,
z: 32223
};
var collection = [{
a: 1,
b: 1,
c: {
x: 10,
y: 20,
z: 30
},
d: 1
},
{
a: 1,
b: 1,
c: {
x: 11,
y: 22,
z: 33
},
d: 1
},
{
a: 1,
b: 1,
c: {
x: 12,
y: 24,
z: 36
},
d: 1
}
];
console.log(find(collection, c));
console.log(find(collection, d));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

Categories

Resources