using array.map to use key of object array of array in typescript - arrays

is there anyway I can use array.map to apply a function that parameter is key of array.object in typescript?
I have one object array inside of array. the object with key min and max. I would like to do something like someArrayFunction(array.map(func1(key), array.map())) so I can compare the value from each key of object array
const allVariables: any[] = [
[ { name: 'a', value:{min: 1, max: 2}, expect: {min: 1, max: 2}}, { name: 'b', value: {min: 11, max: 22}, expect: {min:11, max: 22} }],
[ { name: 'a1',value:{min: 1, max: 2}, expect: {min: 1, max: 2}}, {name: 'b1', value: {min: 11, max: 22}, expect: {min:11, max: 22} }],
[ { name: 'a2',value:{min: 1, max: 2}, expect: {min: 1, max: 2}}, {name: 'b2', value: {min: 11, max: 22}, expect: {min:11, max: 22} }],
];
allVariables.forEach(obj => {
Object.keys(obj).forEach((key) => {
// someArrayFunction(someFunc(obj.name, key), obj.value[key])
// so to compare value.min === expect.min from name a
// so to compare value.min === expect.min from name b
// so to compare value.min === expect.min from name a1
// so to compare value.min === expect.min from name b1
// so to compare value.min === expect.min from name c1
// so to compare value.min === expect.min from name c1
})
})
// someArrayFunction(parameter: string[], v: number){
// do something with parameter and v...
// }

I don't know exactly if you wanted that.
const allVariables: any[] = [
[
{ name: 'a', value:{min: 1, max: 2}, expect: { min: 1, max: 2 } },
{ name: 'b', value: {min: 11, max: 22}, expect: { min:11, max: 22 } },
],
[
{ name: 'a1',value:{min: 1, max: 2}, expect: { min: 1, max: 2 } },
{ name: 'b1', value: {min: 11, max: 22}, expect: { min:11, max: 22} },
],
[
{ name: 'a2',value:{min: 1, max: 2}, expect: { min: 1, max: 2 } },
{ name: 'b2', value: {min: 11, max: 22}, expect: { min:11, max: 22 } },
],
];
allVariables.forEach(array => {
array.forEach(obj => {
const {value, expect} = obj;
console.log(someArrayFunction(obj, value));
})
})
function someArrayFunction(value, expect) {
return value.min === expect.min;
}

Related

RXJS data manipulation

I am trying to find the reactive way of manipulating data in an array of objects. In the array below, I want to determine the low score in groups of four and add a low and diff property to the item.
arr = [
{ name: 'Cliff', score: 44 },
{ name: 'Bob', score: 55 },
{ name: 'Jack', score: 404 },
{ name: 'John', score: 50 },
{ name: 'Doug', score: 22 },
{ name: 'EZ', score: 550 },
{ name: 'Bill', score: 404 },
{ name: 'Dan', score: 5 },
{ name: 'Rich', score: 404 },
{ name: 'Steve', score: 565 },
];
arr$: Observable<Arr[]> = of(this.arr);
getData() {
const scores = this.arr$.pipe(
map((result) =>
result.map((data) => {
return {
x: data.score,
};
})
)
// reduce((acc, x) => (acc = acc > x.score ? acc :x.score), 0)
);
return scores;
}
}
/*
Desired result
arr = [
{ name: 'Cliff', score: 44, low: 44, diff 0 },
{ name: 'Bob', score: 55, low: 44, diff: 9 },
{ name: 'Jack', score: 404, low 44, diff: 360 },
{ name: 'John', score: 50, low: 44, diff: 6 },
{ name: 'Doug', score: 22, low 5, diff: 17 },
{ name: 'EZ', score: 550, low 5, diff: 545 },
{ name: 'Bill', score: 404, low 5, diff: 399 },
{ name: 'Dan', score: 5, low 5, diff: 0 },
{ name: 'Rich', score: 404, low: 404, diff: 0 },
{ name: 'Steve', score: 565. low 404, diff: 121 },
];
*/
I can't seem to get past the few lines of code that I've written. A StackBlitz is here.
This could be a reactive way to get what you want. The comments in the code explain the logic.
// the from rxjs function takes an array and returns an
// Observable that emits each item in the array
from(arr)
.pipe(
// bufferCount will emit an array of arrays of items,
// therefore creates the groups of four items
bufferCount(4),
// for each group we find the low and create
// the new items with the low value and the diff
map((buff) => {
const low = buff.reduce((acc, curr) => {
return acc < curr.score ? acc : curr.score;
}, Infinity);
return buff.map((v) => ({ ...v, low, diff: v.score - low }));
}),
// with mergeMap we flatten the groups of items
// and emit each item
mergeMap((buffEnriched) => buffEnriched),
// if you want to emit an array rather than each single
// object you add toArray
toArray()
)
it makes more sense to sort, then generate your data. otherwise, your output data in your question makes little sense to me.
// DATA IN
arr = [
{ name: 'Cliff', score: 44 },
{ name: 'Bob', score: 55 },
{ name: 'Jack', score: 404 },
{ name: 'John', score: 50 },
{ name: 'Doug', score: 22 },
{ name: 'EZ', score: 550 },
{ name: 'Bill', score: 404 },
{ name: 'Dan', score: 5 },
{ name: 'Rich', score: 404 },
{ name: 'Steve', score: 565 },
];
// PROCESSING and OUTPUT
let lowest = arr[0].score;
let output_arr = arr.sort((a, b)=>{
if(a.score < b.score) return -1;
if(a.score > b.score) return 1;
return 0;
}).map((a)=>{
if(a.score < lowest) lowest = a.score;
return {
name: 'Steve',
score: 565,
low: lowest,
diff: a.score - lowest
};
});
// use output array output
console.log(output_arr);
DEMO
Example
INPUT
[
{ name: 'Cliff', score: 44 },
{ name: 'Bob', score: 55 },
{ name: 'Jack', score: 404 },
{ name: 'John', score: 50 },
{ name: 'Doug', score: 22 },
{ name: 'EZ', score: 550 },
{ name: 'Bill', score: 404 },
{ name: 'Dan', score: 5 },
{ name: 'Rich', score: 404 },
{ name: 'Steve', score: 565 },
]
OUTPUT
[{
diff: 0,
low: 5,
name: "Steve",
score: 565
}, {
diff: 17,
low: 5,
name: "Steve",
score: 565
}, {
diff: 39,
low: 5,
name: "Steve",
score: 565
}, {
diff: 45,
low: 5,
name: "Steve",
score: 565
}, {
diff: 50,
low: 5,
name: "Steve",
score: 565
}, {
diff: 399,
low: 5,
name: "Steve",
score: 565
}, {
diff: 399,
low: 5,
name: "Steve",
score: 565
}, {
diff: 399,
low: 5,
name: "Steve",
score: 565
}, {
diff: 545,
low: 5,
name: "Steve",
score: 565
}, {
diff: 560,
low: 5,
name: "Steve",
score: 565
}]

How to group array and count values

I have an array that I want to group according to type then count the number of instances for every unique status.
Here is my array:
const array = [
{ type: 'A', number: 2, status:'Approved', year: '2020' },
{ type: 'A', number: 3, status:'Approved', year: '2020' },
{ type: 'A', number: 3, status:'Disapproved', year: '2020' },
{ type: 'A', number: 6, status:'Disapproved', year: '2020' },
{ type: 'A', number: 5, status:'Processing', year: '2020' },
{ type: 'B', number: 8, status:'Processing', year: '2020' },
{ type: 'B', number: 2, status:'Approved', year: '2020' },
{ type: 'B', number: 2, status:'Disapproved', year: '2020' },
]
Here is my desired array:
const desiredArray = [
{ type: 'A', Approved:5, Disapproved: 9, Processing: 13, year: '2020' },
{ type: 'B', Approved:2, Disapproved: 2, year: '2020' },
]
With help from other online friends, this worked perfectly:
const reducedObject = array.reduce((rv,x) =>{
if(!rv[x.type]) {
rv[x.type] = {
type: x.type,
Approved: 0,
Disapproved: 0,
Processing: 0,
year: x.year
}
}
rv[x.type][x.status]++;
return rv;
}, {});
const desiredArray = Object.values(reducedObject);
Another answer:
var array = [
{ Id: "001", qty: 1 },
{ Id: "002", qty: 2 },
{ Id: "001", qty: 2 },
{ Id: "003", qty: 4 }
];
var result = [];
array.reduce(function(res, value) {
if (!res[value.Id]) {
res[value.Id] = { Id: value.Id, qty: 0 };
result.push(res[value.Id])
}
res[value.Id].qty += value.qty;
return res;
}, {});
console.log(result)

Adding new property using forEach in an array of objects

I have 2 arrays of objects. I would like to add a category property to each object in values, example: 50 should fall in the range 41 to 70
let values = [
{1: 124},
{2: 50},
{3: 65},
{4: 21}
];
let categories = [
{cat: "Category1", min: 5, max: 40},
{cat: "Category2", min: 41, max: 70},
{cat: "Category3", min: 71, max: 130}
];
How do I get my result as, using array method forEach():
[
{1: 124, category: "Category3"},
{2: 50, category: "Category2"},
{3: 65, category: "Category2"},
{4: 21, category: "Category1"}
]
Not an optimized one but satisfies the requirement.
let result = [];
values.forEach(element => {
categories.forEach(col => {
let current = Object.values(element)[0];
if(current >= col.min && current <=col.max){
element["category"] = col.cat;
}
})
result.push(element);
})

Merge two arrays avoiding O(n^2) complexity

Given two arrays, farmers and collections, I want to be able to merge the farmer information to each collection when farmer_id in the collection is equal to id in farmers. if there is no id of the farmer that matches farmer_id in the collection then that collection should have a an empty farmer object
const farmers = [{
id: 10,
name: 'John Doe',
email: 'jdoe#gmail.com'
},
{
id: 11,
name: 'James Bond',
email: 'james#gmail.com'
}
]
const collections = [{
id: 9,
name: 'Book',
farmer_id: 10,
date: 'June'
},
{
id: 10,
name: 'Game',
farmer_id: 11,
date: 'July'
},
{
id: 13,
name: 'Car',
farmer_id: 10,
date: 'August'
},
{
id: 11,
name: 'Wristwatches',
farmer_id: 20,
date: 'August'
}
]
The result should be in this format below
const result = [{
id: 9,
name: 'Book',
farmer_id: 10,
date: 'June',
farmer: {
id: 10,
name: 'John Doe',
email: 'jdoe#gmail.com'
}
},
{
id: 10,
name: 'Game',
farmer_id: 11,
date: 'July',
farmer: {
id: 11,
name: 'James Bond',
email: 'james#gmail.com'
}
},
{
id: 13,
name: 'Car',
farmer_id: 10,
date: 'August',
farmer: {
id: 10,
name: 'John Doe',
email: 'jdoe#gmail.com'
}
},
{
id: 11,
name: 'Wristwatches',
farmer_id: 20,
date: 'August',
farmer: {}
}
]
This is what i have been able to come up with but am stuck right now
function mapper(farmers, collectors) {
for (let k = 0; k < farmers.length; k++) {
const idToFarmerInfo = {};
idToFarmerInfo[farmers[k].id] = farmers[k];
for (let j = 0; j < collectors.length; j++) {
let mapper = idToFarmerInfo[collectors[j].farmer_id];
farmers[mapper] = collectors[j]
}
}
return farmers
}
i followed this link as am trying to avoid O of N squared but O of N complexity
For a better performance you could create a hash of farmers where the complexity is O(N) because we're iterating the farmers list only once.
const farmers = [{ id: 10, name: 'John Doe', email: 'jdoe#gmail.com' }, { id: 11, name: 'James Bond', email: 'james#gmail.com' } ]; const collections = [{ id: 9, name: 'Book', farmer_id: 10, date: 'June' }, { id: 10, name: 'Game', farmer_id: 11, date: 'July' }, { id: 13, name: 'Car', farmer_id: 10, date: 'August' }, { id: 11, name: 'Wristwatches', farmer_id: 20, date: 'August' } ]
var farmers_hash = farmers.reduce((hash, item) => {
hash[item.id] = item;
return hash;
}, {});
console.log(farmers_hash);
The following step is to build the desired output by assigning one farmer using hash keys.
This can be achieved using map method in combination with Object.assign.
const farmers = [{ id: 10, name: 'John Doe', email: 'jdoe#gmail.com' }, { id: 11, name: 'James Bond', email: 'james#gmail.com' } ]; const collections = [{ id: 9, name: 'Book', farmer_id: 10, date: 'June' }, { id: 10, name: 'Game', farmer_id: 11, date: 'July' }, { id: 13, name: 'Car', farmer_id: 10, date: 'August' }, { id: 11, name: 'Wristwatches', farmer_id: 20, date: 'August' } ]
var farmers_hash = farmers.reduce((hash, item) => {
hash[item.id] = item;
return hash;
}, {});
var result = collections.map((item) => {
item.farmer = Object.assign({}, farmers_hash[item.farmer_id])
return item;
});
console.log(result);
As you can see the final complexity is O(N) + O(M) where N is the length of farmers array and M is the length of collections array.
Demo on stackblitz
You can use a more declarative approach and use Array.map and Array.find
const result = collections.map(collection => {
return {
...collection,
farmer: farmers.find(farmer => collection.farmer_id == farmer.id) || {}
};
});
console.log(result);
You can create a Map collection to have O(N) of access to desired farmer by id. Then mapping becomes faster in terms of performance:
const unique = new Map(farmers.map(f=> [f.id, f]));
const result = collections.map(s => ({
...s, farmer_id: unique.get(s.farmer_id) || s.farmer_id
}))
Now mapping of collections has complexity O(N). However, do not forget to sum complexity of making unique farmers. The overall complexity is O(N) + O(M).
An example:
const farmers = [{
id: 10,
name: 'John Doe',
email: 'jdoe#gmail.com'
},
{
id: 11,
name: 'James Bond',
email: 'james#gmail.com'
}
];
const collections = [{
id: 9,
name: 'Book',
farmer_id: 10,
date: 'June'
},
{
id: 10,
name: 'Game',
farmer_id: 11,
date: 'July'
},
{
id: 13,
name: 'Car',
farmer_id: 10,
date: 'August'
},
{
id: 11,
name: 'Wristwatches',
farmer_id: 20,
date: 'August'
}
];
const unique = new Map(farmers.map(f=> [f.id, f]));
const result = collections.map(s => ({
...s, farmer_id: unique.get(s.farmer_id) || s.farmer_id
}))
console.log(result);

How to filter multiple objects from a list objects by a property array?

I have a object array in which each object contain an id and a name and a separate array contains a set of ids. I want to filter first array based on the second array.
const data= [
{
id: 1,
name: 'name1'
},
{
id: 2,
name: 'name2'
},
{
id: 3,
name: 'name3'
},
{
id: 4,
name: 'name4'
}
];
const array = [1,3,4];
const expectedResult= [
{
id: 1,
name: 'name1'
},
{
id: 3,
name: 'name3'
},
{
id: 4,
name: 'name4'
}
];
Use .filter and .includes
const data= [
{
id: 1,
name: 'name1'
},
{
id: 2,
name: 'name2'
},
{
id: 3,
name: 'name3'
},
{
id: 4,
name: 'name4'
}
];
const array = [1, 3, 4]
const result = data.filter((item) => {
//gives us items that passes a condition
return array.includes(item.id)
})
console.log(result)

Resources