js common function which calculates and assign to object values? - javascript

Example of what i'm trying to achieve
I want to make an object in react which will calculate one its key value from other keys using this function and the 'this' keyword so that I can use this function dynamically with many input fields object.
func = function (c) {
return this.a + this.b + c;
};
obj1 = {
a: 1,
b: 2,
value: func(5),
};
obj2 = [
{ a: 2, b: 3, value: func(6) },
{
a: 4,
b: 5,
value: func(7),
},
];
// expected result
console.log(obj1.value); // 8
console.log(obj2[0].value); // 16

I guess the simplest solution would to flip this around: Pass the object to the function, let it add the property and return the very same object:
const func = function (obj, c) {
obj.value = obj.a + obj.b + c;
return obj;
};
const obj1 = func({
a: 1,
b: 2,
}, 5);
const obj2 = [
func({ a: 2, b: 3 }, 6),
func({
a: 4,
b: 5,
}, 7),
];
// expected result
console.log(obj1.value); // 8
console.log(obj2[0].value); // 16
(no idea how the second example would result in 16 though)

At the moment func is called, this is set to window object, because the object you want to use it in, doesn't exist yet.
You can try returning a function from func
const func = function(c) {
return function() {
return this.a + this.b + c
}
}
const obj1 = {
a: 1,
b: 2,
value: func(5),
}
const obj2 = [{
a: 2,
b: 3,
value: func(6)
},
{
a: 4,
b: 5,
value: func(7)
}
]
// expected result
console.log(obj1.value()) // 8
console.log(obj2[0].value()) // 11

Related

Dynamically sort object by key provided in a variable

What's wrong with this code? Why cant it sort the array according to the a key of the object?
It works when using dot notation in the condition but I want to use the second parameter in the condition instead of dot notation. Please help me getting the result.
This works:
if (objSort[i][`sortBy`] > objSort[j][`sortBy`]) {
[objSort[i], objSort[j]] = [objSort[j], objSort[i]]
}
This does not work:
function sortData(objSort, sortBy) {
for (let i = 0; i < objSort.length; i++) {
for (let j = i + 1; j < objSort.length; j++) {
if (objSort[i][`sortBy`] > objSort[j][`sortBy`]) {
[objSort[i], objSort[j]] = [objSort[j], objSort[i]]
}
}
}
console.log(data);
}
const data = [{ a: 4, b: 5 }, { a: 1, b: 10}, { a: 2, b: 5 }, { a: 14, b: 15 }, { a: 12, b: 3 }];
sortData(data,'a');
sortBy is your variable name, so remove it from the template literal:
if (objSort[i][sortBy] > objSort[j][sortBy]) {
That being said, your code is much more complex than it needs to be - there's no need for two loops and reorganising the array - just use sort():
const sortData = (objSort, sortBy) => objSort.sort((a, b) => a[sortBy] - b[sortBy]);
const data = [{ a: 4, b: 5 }, { a: 1, b: 10}, { a: 2, b: 5 }, { a: 14, b: 15 }, { a: 12, b: 3 }];
const result = sortData(data,'a');
console.log(result);

Get an element object of an array from a key name

I'm parsing a csv fils to json with node-csvtojson and I got a JSONarray with the following code
csv({delimiter: ';'}).fromFile(path).then((jsonObj)=>{
data = jsonObj;
console.log(jsonObj);
})
with a csv like
a,b,c
A,B,C
1,2,3
1,B,C
I have got
[
{
a: A,
b: B,
c: C,
},
{
a: 1,
b: 2,
c: 3,
},
{
a: 1,
b: B,
c: C
}
]
But I want to find every object who has the element a === 1 and I want to have all the content of the object,
like this:
{
a: 1,
b: 2,
c: 3,
},
{
a: 1,
b: B,
c: C,
}
But I 'm struggling to do that, I have tried with array.filter but without success then I have tried to do this with array.map but I got lost on how to do.
Do you have any idea on or I could do that ?
Than you
Use Array.filter like so:
const data = [{
a: 'A',
b: 'B',
c: 'C',
},
{
a: 1,
b: 2,
c: 3,
},
{
a: 1,
b: 'B',
c: 'C'
}
];
console.log(data.filter(({ a }) => a == 1));
If you want this to work with old browsers, here's an ES5-compliant version:
var data = [{
a: 'A',
b: 'B',
c: 'C',
},
{
a: 1,
b: 2,
c: 3,
},
{
a: 1,
b: 'B',
c: 'C'
}
];
console.log(data.filter(function(obj) {
return obj.a == 1
}));
Simple use Array.filter to filter through the object array and select the one having property a === 1
var arr = [{"a":"A","b":"B","c":"C"},{"a":1,"b":2,"c":3},{"a":1,"b":"B","c":"C"}];
const filteredArr = arr.filter(obj => obj.a === 1);
console.log(filteredArr);
Using Array.reduce you can do the same thing:
var arr = [{"a":"A","b":"B","c":"C"},{"a":1,"b":2,"c":3},{"a":1,"b":"B","c":"C"}];
const redArr = arr.reduce((acc, obj) => {
return acc = obj.a === 1 ? acc.concat(obj) : acc;
}, []);
console.log(redArr);
Using Array.map for this problem is not the right approach, although it is possible:
var arr = [{"a":"A","b":"B","c":"C"},{"a":1,"b":2,"c":3},{"a":1,"b":"B","c":"C"}];
const mapArr = arr.map(obj => obj.a === 1 ? obj : undefined).filter(obj => obj); //hack to remove undefined elements
console.log(mapArr);
console.log([{
a: 'A',
b: 'B',
c: 'C',
},
{
a: 1,
b: 2,
c: 3,
},
{
a: 1,
b: 'B',
c: 'C'
}
].filter(o => o.a === 1))
Try this :
var arr = [{"a":"A","b":"B","c":"C"},{"a":1,"b":2,"c":3},{"a":1,"b":"B","c":"C"}];
var res = arr.filter(obj => obj.a === 1);
console.log(res);

Using key from another object to use in a new object

I'm trying the following:
let foo = { a: 3, b: 4 };
let bar = { foo.a: 1, foo.b: 2 };
This doesn't work and to achieve this I'll have to do this:
let foo = { a: 3, b: 4 };
const c = foo.a;
const d = foo.b;
let bar = { c: 1, d: 2 };
Is there a way to do this using my first example?
Use computed property names:
let bar = { [foo.a]: 1, [foo.b]: 2 };
Example:
let foo = { a: 3, b: 4 };
let bar = { [foo.a]: 1, [foo.b]: 2 };
console.log(bar);

From an array of objects, how to return property `b` of the object that has the highest property `a`?

I need to get the value of the property b from the object with the highest value of the property a.
var myArr = [
{
a: 1,
b: 15
},
{
a: 2,
b: 30
}
];
I tried the following, but it just returns the highest value of a, rather than of b.
var res = Math.max.apply(Math,myArr.map(function(o){return o.a;});
var blah = getByValue(myArr);
Use Array#reduce, and on each iteration take the object with the highest a value:
var myArr = [{"a":1,"b":15},{"a":2,"b":30}];
var result = myArr.reduce(function(o, o1) {
return o.a > o1.a ? o : o1;
}).b;
console.log(result);
Can sort a copy then get first or last depending on sort direction:
var myArr = [
{
a: 1,
b: 15
},
{
a: 2,
b: 30
}
];
var highest = myArr.slice().sort((a,b)=>a.a-b.a).pop().b
console.log(highest)
Using reduce
You can use .reduce() to find the element with the maximum a value and then just grab its b value, like this:
var myArr = [{
a: 1,
b: 15
},
{
a: 2,
b: 30
}
];
var max = myArr.reduce(function(sum, value) {
return (sum.a > value.a) ? sum : value;
}, myArr[0]);
console.log(max.b);
Using sort
A bit more unorthodox approach is to use .sort() to sort the array in descending order in terms of its property a and then get the first element's b value, like this:
var myArr = [{
a: 1,
b: 15
},
{
a: 2,
b: 30
}
];
var max = myArr.sort(function(value1, value2) {
return value1.a < value2.a;
})[0];
console.log(max.b);
Try this:
var myArr = [
{
a: 1,
b: 15
},
{
a: 2,
b: 30
}
];
var res = myArr.map(function(o){return o.b;});
myArr.sort(function (o1, o2) {
return o1.a < o2.a;
})
console.log(myArr[0].b);

Return an Array of Arrays containing objects that share a common value in a property

Say I have an array of 3 objects like this:
[
{
a: 4,
b: 5,
c: 4
},
{
a: 3,
b: 5,
c: 6
},
{
a: 2,
b: 3,
c: 3
}
]
I would like to return an array of arrays containing the objects that share a common value for the property b. So the resulting array would contain only one array containing 2 objects like this:
[
[
{
a: 4,
b: 5,
c: 4
},
{
a: 3,
b: 5,
c: 6
}
]
]
How would I do this?
You could do this with map and filter
var data = [{"a":4,"b":5,"c":4},{"a":3,"b":5,"c":6},{"a":2,"b":3,"c":3}];
var check = data.map(e => {return e.b});
var result = [data.filter(e => { return check.indexOf(e.b) != check.lastIndexOf(e.b)})];
console.log(result)
To group multiple objects in separate arrays with same b values you can use map and forEach
var data = [{"a":4,"b":5,"c":4},{"a":3,"b":5,"c":6},{"a":2,"b":3,"c":3}, {"a":3,"b":7,"c":6},{"a":2,"b":7,"c":3}], result = [];
var check = data.map(e => {return e.b});
data.forEach(function(e) {
if(check.indexOf(e.b) != check.lastIndexOf(e.b) && !this[e.b]) {
this[e.b] = [];
result.push(this[e.b]);
}
(this[e.b] || []).push(e);
}, {});
console.log(result)
This proposal uses a single loop with Array#forEach but without Array#indexOf.
var array = [{ a: 4, b: 5, c: 4 }, { a: 3, b: 5, c: 6 }, { a: 2, b: 3, c: 3 }],
grouped = [];
array.forEach(function (a) {
this[a.b] = this[a.b] || [];
this[a.b].push(a);
this[a.b].length === 2 && grouped.push(this[a.b]);
}, Object.create(null));
console.log(grouped);
You can create a function that accepts fulfillment criteria and will return as many nested arrays as rules passed.
Let's say you have an array of objects, arr.
var arr = [{a: 1, b: 2}, {a: 3, b: 2}, {a: 3, b: 4}, {a: 1, b: 1}]
And you want to return an array with with nested arrays that fulfill a particular requirement, let's say you want objects with an a:1 and b:2.
You can create a function that loops through your rules and creates a nested array with the objects that fulfill each rule.
For example:
var arr = [{a: 1, b: 2}, {a: 3, b: 2}, {a: 3, b: 4}, {a: 1, b: 1}]
function makeNestedArrays() {
var rules = [].slice.call(arguments);
return rules.reduce(function(acc, fn) {
var nestedArr = [];
arr.forEach(function(obj) {
if (fn(obj)) {
nestedArr.push(obj);
}
});
// only push nested array
// if there are matches
if (nestedArr.length) {
acc.push(nestedArr);
}
return acc;
}, []);
}
var result = makeNestedArrays(
function(obj) { return obj.a === 1; },
function(obj) { return obj.b === 2; }
);
console.log(result);
This allows you to pass as many "rules" as you want, and will create a nested array for each rule so long as there is at least one match.
You could use a Map to group them, this should work with any kind of value (just be sure the equality rules check out):
var arr = [{
a: 4,
b: 5,
c: 4
}, {
a: 3,
b: 5,
c: 6
}, {
a: 2,
b: 3,
c: 3
}];
var result = arr.reduce(function(m, o){
var value = o.b;
if(m.has(value)){
m.get(value).push(o);
} else {
m.set(value, [o]);
}
return m;
}, new Map());
console.log(...(result.values()));
If you'd need to filter out the groups of 1:
var arr = [{
a: 4,
b: 5,
c: 4
}, {
a: 3,
b: 5,
c: 6
}, {
a: 2,
b: 3,
c: 3
}];
var result = arr.reduce(function(m, o){
var value = o.b;
if(m.has(value)){
m.get(value).push(o);
} else {
m.set(value, [o]);
}
return m;
}, new Map());
result = [...result.values()].filter(a => a.length > 1);
console.log(result);

Categories

Resources