Sort array containing objects based on another array [duplicate] - javascript

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
JavaScript - Sort an array based on another array of integers
Javascript - sort array based on another array
If I have an array like this:
['one','four','two']
And another array like this:
[{
key: 'one'
},{
key: 'two'
},{
key: 'four'
}]
How would I sort the second array so it’s key property follows the order of the first? In this case, I want:
[{
key: 'one'
},{
key: 'four'
},{
key: 'two'
}]

We can use the sort() function to do this by passing it a custom function which does the comparison. This function has to return 3 possible values given a or b to compare:
return -1 if a is indexed lower than b
return 0 if a is considered equal to b
return 1 if a is indexed greater than b
With this in mind, we can define a function such as this:
function sortFunction(a,b){
var indexA = arr.indexOf(a['key']);
var indexB = arr.indexOf(b['key']);
if(indexA < indexB) {
return -1;
}else if(indexA > indexB) {
return 1;
}else{
return 0;
}
}
This function will take in the objects you defined in your array, and find where that value is in the arr array, which is the array you're comparing to. It then compares the index, and returns the values as needed.
We use this function by passing the function into the sort() function as such:
testArray.sort(sortFunction)
where testArray is the array you're trying to sort.
You can take a look at here, where I did this example, and you can see the second object in your array being "alerted" to you, before and after the sort function was called. http://jsfiddle.net/Sqys7/

Here's my take on it:
function orderArray(array_with_order, array_to_order) {
var ordered_array = [],
len = array_to_order.length,
len_copy = len,
index, current;
for (; len--;) {
current = array_to_order[len];
index = array_with_order.indexOf(current.key);
ordered_array[index] = current;
}
//change the array
Array.prototype.splice.apply(array_to_order, [0, len_copy].concat(ordered_array));
}
Sample implementation:
var array_with_order = ['one', 'four', 'two'],
array_to_order = [
{key: 'one'},
{key: 'two'},
{key: 'four'}
];
orderArray(array_with_order, array_to_order);
console.log(array_to_order); //logs [{key: 'one'}, {key: 'four'}, {key: 'two'}];
The usual fiddle: http://jsfiddle.net/joplomacedo/haqFH/

Related

How to select all objects within an array by their key and add their values together?

So here's what I'm trying to do, I have an application I've been working on that allows users to read articles and take quizzes on them, each article is contained in a category. Category has an _id which is unique. Quiz attempts are held within another table which refrences the article, which refrences the category.
I have looped through all of the quiz attempts and store their keys and values in an array of objects which looks like the following:
const userScoreArray = [];
for(let i = 0; i < data[1].length; i++) {
userScoreArray.push({[data[1][i]['dataValues']['article_id']]: data[1][i]['dataValues']['score'] }) // overall
}
Now I have an array which stores quiz attempts for each category:
[
{4: 5},
{4: 1},
{3: 6},
{5: 0}
// { category: score }
]
How would I be able to get into this array, select all objects with the key of "4" and and then add all of their values together, and then again grab all objects with the key of "5" and add their values together? I was thinking of using a loop to do it but my brain starts to steam right then.
You can use an Array.reduce iterator, then Object.keys() and Object.values() to extract the numbers for comparing and adding
let data = [
{4: 5},
{4: 1},
{3: 6},
{5: 0}
// { category: score }
];
const getScoreFor = n => {
return data.reduce((b, a) => {
return b + (Object.keys(a)[0] == n ? Object.values(a)[0] : 0);
}, 0);
}
console.log(getScoreFor(4))
You can use the reduce method as follows:
const array = [{ 4: 5 }, { 4: 1 }, { 3: 6 }, { 5: 0 }];
const accArray = array.reduce((acc, obj) => {
if (obj[4] ?? obj[5]) {
acc += Object.values(obj)[0];
}
return acc;
}, 0);
console.log(accArray); // 6
MDN ref.:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
By using reduce(), you loop through the array having access at each iteration to an accumulator, the current element and the current index. The initial value of the accumulator, on the above example, is set to zero; at each iteration, we check if the object has a key equal to 4 or 5; if the condition is true we add to the accumulator the value of that object, then it is returned the accumulator (because that is how the reduce method works).
OBS: I used the nullish coalescing operator (??) just in case you need to use 0 as key ({0: any_value}), as the or operator (||) works with falsy values.

Deduplicate array of objects by given property name

I have an array of objects with about 1500 elements, I am trying to make a new array removing the elements that have a duplicate unique property. But for some reason when I run the function it stops at the first 100 elements of the array. How can I get it to loop through the whole array.
const result = Array.from(new Set(DATA.map((a) => a.Numbers))).map(
(Numbers) => {
return DATA.find((a) => a.Numbers === Numbers);
}
);
Create an object that uses the Numbers property as the keys. Since object keys must be unique, this will remove duplicates. Then get the object values to convert back to an array.
const DATA = [{ Numbers: 1 },{ Numbers: 2 },{ Numbers: 3 },{ Numbers: 4 },{ Numbers: 1 },{ Numbers: 4 }];
const result = Object.values(Object.fromEntries(DATA.map(a => [a.Numbers, a])));
console.log(result)
You're really complicating matters. You're mapping twice, converting the result into a set, and then creating a new array from that set.
It would be much simpler (and more readable) to use a simple loop, and keep a record of the numbers in the objects. If a number already exists splice the object from the array.
This method won't create a new array - you're modifying the existing one - but it will work.
const arr = [{ number: 1 },{ number: 2 },{ number: 3 },{ number: 4 },{ number: 1 },{ number: 4 }];
const numbers = new Set();
for (let i = arr.length - 1; i >= 0 ; i--) {
const { number } = arr[i];
if (numbers.has(number)) arr.splice(i, 1);
numbers.add(number);
}
console.log(arr);
Since no Map-based answers yet (and I believe, Map suits the purpose the best from performance standpoint), I'll post mine:
const src = [{key: 'a', value: 1}, {key: 'c', value: 3}, {key: 'b', value: 2}, {key: 'a', value: 1}, {key: 'c', value: 3}]
const dedupe = (arr, keyProp) => [
...arr
.reduce((acc, obj) =>
(acc.set(obj[keyProp], obj), acc), new Map)
.values()
]
const result = dedupe(src, 'key')
console.log(result)
.as-console-wrapper{min-height:100%;}
The idiom for making an array of distinct objects (also described in this answer) goes like this:
const distinct = DATA.filter((obj, idx) =>
idx === data.findIndex(a => a.Numbers === obj.Numbers));
This filters the input array by selecting all items that, when linearly searched for, return the same index they already have. Thus selecting the first of each such object with the given criteria.
Note: that some of your Numbers were strings and some were actual numbers. (Those with a leading 0 were stored as strings, like '02'.) You could use the less strict == instead of === if you need to deal with situations where the same value may be stored in both string and number format. e.g.: a.Numbers == obj.Numbers.

Opposite of shift() in JS or other solutions [duplicate]

This question already has answers here:
Rotate the elements in an array in JavaScript
(42 answers)
Closed 5 years ago.
I am trying to take an array and have it loop around itself. I already found a simple solution for having it loop around itself backwards:
array = ['Dog', 'Cat', 'Animal', 'Pig']
array[array.length] = array[0];
array.shift();
This as expected turns out as ['Cat', 'Animal', 'Pig', 'Dog']. How would I make it do the opposite in a similar manner. By doing the opposite I mean turning out ['Pig', 'Dog', 'Cat', 'Animal']. I have tried to find the opposite of .shift() for this but can't find anything. Thank you for your time.
You could Array#pop
The pop() method removes the last element from an array and returns that element. This method changes the length of the array.
and Array#unshift.
The unshift() method adds one or more elements to the beginning of an array and returns the new length of the array.
var array = ['Dog', 'Cat', 'Animal', 'Pig'];
array.push(array.shift());
console.log(array); // ["Cat", "Animal", "Pig", "Dog"]
array = ['Dog', 'Cat', 'Animal', 'Pig'];
array.unshift(array.pop());
console.log(array); // ["Pig", "Dog", "Cat", "Animal"]
It looks like you're looking for a rotate function:
Array.prototype.rotate = (function() {
// save references to array functions to make lookup faster
var push = Array.prototype.push,
splice = Array.prototype.splice;
return function(count) {
var len = this.length >>> 0, // convert to uint
count = count >> 0; // convert to int
// convert count to value in range [0, len)
count = ((count % len) + len) % len;
// use splice.call() instead of this.splice() to make function generic
push.apply(this, splice.call(this, 0, count));
return this;
};
})();
a = [1,2,3,4,5];
a.rotate(1);
console.log(a.join(',')); //2,3,4,5,1
a.rotate(-1);
console.log(a.join(',')); //1,2,3,4,5
a.rotate(-1);
console.log(a.join(',')); //5,1,2,3,4

How to compare two JSON values based on the key name in javascript?

I have two JSON arrays like
array1=[{a:1,b:2,c:3,d:4}]
&
array2=[{a:2,b:5,c:3,d:4}]
Is there any method to find the value of one of the keys in array1 present in array 2.Here in the array 1 key b contains the value 2,and array2 also contain a key a with value 2. How can I capture the key name of array 2 which has the same value for one of the keys in array.
I don't quite understand if you are interested in operating on arrays or objects - as your example is a pair of single element arrays, and the comparison is clearly between the objects in the arrays.
That said, if your goal is to compare two objects, and return the set of keys that are the same for both, you would do something like
obj1 = {a:1,b:2,c:3,d:4};
obj2 = {a:2,b:5,c:3,d:4};
function sameKeys(a,b) {
return Object.keys(a).filter(function(key) {
return a[key] === b[key];
});
}
console.log(sameKeys(obj1, obj2));
When I run this, I get:
[ 'c', 'd' ]
I hope that is what you were asking...
Wrote a prototype function to compare an object against another.
var obj1 = {a: 1, b: 2, c: 3, d: 4};
var obj2 = {a: 2, b: 4, c: 100, d: 200}
Object.prototype.propertiesOf = function(visitorObj) {
result = {};
//Go through the host object
for (thisKey in this) {
//Exclude this function
if (!this.hasOwnProperty(thisKey))
continue;
//Compare the visitor object against the current property
for (visitorKey in visitorObj) {
if (visitorObj[visitorKey] === this[thisKey])
result[visitorKey] = thisKey;
}
}
return result;
}
console.log(obj1.propertiesOf(obj2));
Simply call the propertiesOf function of any object by passing another object as the argument. It returns an object which has similar keys linked to each other.
The above example will result in:
{a: "b", b: "d"}
It seems you want something like this: make a function that finds all the keys in the 2nd object that have a given value. Then pass the value from the first object to that function.
obj1={a:1,b:2,c:3,d:4};
obj2={a:2,b:5,c:3,d:4};
function findKeysByValue(obj, v) {
var results = [];
for (var k in obj) {
if (obj.hasOwnProperty(k) && v == obj[k]) {
results.push(k);
}
}
return results;
}
console.log(findKeysByValue(obj2, obj1['b'])); // ['a']

Sorting a value pair in Javascript

I must be missing the proper term or else I'm sure I could find the answer by searching... in any case, here's what I want to do.
Through javascript, I get four variables (A, B, C, and D) that I would like to sort, and still keep track of the variable name (since it's encoded with meaning information).
Sample Data:
A = 2;
B = 1;
C = 4;
D = 3;
What I need to do now is sort them in value order (4,3,2,1) such that I can actually know the variable name ordering (C,D,A,B).
You can keep an array of value pair objects and then simply sort that array. Of course, the array's sort method need to know how to interpret the object but that can be done by supplying a comparison function to the sort method.
First declare your array of objects:
sample_data = [
{ name: 'A', value: 2 },
{ name: 'B', value: 1 },
{ name: 'C', value: 4 },
{ name: 'D', value: 3 }
];
Then write a comparison function:
function custom_compare (a,b) {
// I'm assuming all values are numbers
return a.value - b.value;
}
Then simply sort and reverse:
sample_data.sort(custom_compare).reverse();
To print out the sorted names simply iterate through the array:
for (var i=0;i<sample_data.length;i++) {
console.log(sample_data[i].name);
}
May it help you:
https://github.com/shinout/SortedList
This is sortedlist library.
I think what you should be looking for something like "Associative arrays" implemented in Javascript.
Check this earlier thread for your answer.

Categories

Resources