Merge two Object based on Object one value with Object two key - javascript

Want to merge object key values with another object value.
Suppose results object key should match with headers object key_name match because header should be CamelCase.
I have headers object is:
let headers = [
{ key_name: 'pid', header_value: 'PID' },
{
key_name: 'card_no',
header_value: 'Card Number'
},
{
key_name: 'trans_id',
header_value: 'Transaction ID'
},
{
key_name: 'card_name',
header_value: 'Card Name'
}
]
results Object is:
let results = let results = [
{
pid: '1234567890',
card_no: '546.......3742',
trans_id: '2019124453159',
card_name: 'Mastercard',
code: '$'
},
{
pid: '1234567890',
card_no: '546.......3742',
trans_id: '2019120534555',
card_name: 'Visa',
code: 'INR'
}
]
Header object key_name matching values need to filter in final results Object like below.
expected results is:
let results = [
{
PID: '1234567890',
Card Number: '546.......3742',
Transaction ID: '2019124453159',
Card Name: 'Mastercard'
},
{
PID: '1234567890',
Card Number: '546.......3742',
Transaction ID: '2019120534555',
Card Name: 'Visa'
}
]
I tried with below script its returning all values only:
for (let index = 0; index < results.length; index++) {
for (let i = 0; i < headers.length; i++) {
console.log(results [index][header[i].key_name])
}
}

I would suggest turning the first object into a map, so you have faster look-up. Then turn your objects into key/value pairs with Object.entries, perform the mapping and the filtering, and then turn those pairs back to an object with Object.fromEntries
let headers = [{ key_name: 'pid', header_value: 'PID' },{key_name: 'card_no',header_value: 'Card Number'},{key_name: 'trans_id',header_value: 'Transaction ID'},{key_name: 'card_name',header_value: 'Card Name'}];
// Convert to map:
let map = new Map(headers.map(({key_name, header_value}) => [key_name, header_value]));
let arr = [{pid: '1234567890',card_no: '546.......3742',trans_id: '2019124453159',card_name: 'Mastercard',code: '$'},{pid: '1234567890', card_no: '546.......3742',trans_id: '2019120534555',card_name: 'Visa',code: 'INR'}];
// Use map to make transition
let result = arr.map(obj =>
Object.fromEntries(Object.entries(obj).map(([key, value]) =>
map.has(key) && [map.get(key), value]
).filter(Boolean))
);
console.log(result);

You could look into the Object.keys(..) of the results array so you can map the old key values to the new ones.
You could use something like this:
const mappedHeaders = results.map((r) => {
const keys = Object.keys(r);
let newObj = {};
for (const key of keys) {
const newHeader = headers.find((h) => h.key_name === key);
if (newHeader) newObj[newHeader.header_value] = r[key];
}
return newObj;
});
You may need to check if the mapping exists and handle such cases to avoid errors.

Related

NodeJS - Match JSON Arrays and send email to user - Gives empty coins arrays

I'm new to NodeJS and started to build out a serverless function to
Match custom_alerts criteria to crypto_signals data and send an email to the user.
I'm stuck in my loop trying to for that email combine all matching customAlerts and then create an array that matches customAlerts.signals_selection to cryptoSignals.combo_signal
The issue is here (see all code below for context) since one is an array and one is not
customObject.coins = cryptoSignalList.filter(item => item.combo_signal == x.signals_selection.includes(item))
I'm trying to use filter, reduce stuff for the first time.
Current Output
[
{ name: 'only Very Positive', coins: [] },
{ name: 'Only negative', coins: [] }
]
Output Goal
To send an email to the user with all the coins that match their criteria from custom_alerts. To create the email I'm thinking In the loop create an array that looks like below so I can use that in the body of the email
[
{
"name": customAlerts.name
"coins": [
{
"coin": cryptoSignals.coin,
"combo_signal": cryptoSignals.combo_signal
}
]
},
{
"name": customAlerts.name
"coins": [
{
"coin": cryptoSignals.coin,
"combo_signal": cryptoSignals.combo_signal
}
]
}
]
Data examples
Cryptosignals output example
[{
id: 119,
coin: 'iExec RLC',
coin_abr: 'RLC',
combo_signal: 'Negative',
combo_change: true,
combo_prev_signal: 'Very Negative'
}
]
customAlerts output example
[{
id: 8,
created_at: '2022-03-01T07:58:48.963809+00:00',
user_id: 'test12345',
signals_selection: [ 'Very Positive', 'Positive' ],
categories_selection: [ 'combo_signal' ],
name: 'Only Positive',
profiles: { email: 'email#email.com' }
}
]
My code
const matchAlertSignal = (emailList, customAlertList, cryptoSignalList) => {
const testArray = []
for (let i of emailList) { //loop through the email list
const emailAlertFilter = customAlertList.filter((customAlertList) => customAlertList.profiles.email == i )
const filterArray = []
for(let x of emailAlertFilter) {
const customObject = {}
customObject.name = x.name
customObject.coins = cryptoSignalList.filter(item => item.combo_signal == x.signals_selection.includes(item))
filterArray.push(customObject)
}
testArray.push(filterArray)
}
console.log(testArray)
}
async function main(){
let cryptoSignals = await getCryptoSignals();
let customAlerts = await getCustomAlerts();
let supabaseEmails = userEmail(customAlerts);
let customFilter = matchAlertSignal(supabaseEmails, customAlerts, cryptoSignals);
I see two issues with the current version of your question:
matchAlertSignaldoes not return a value
The filtering on cryptoSignalList seems incorrect as you test equality between combo_signal (string) and the fact that the emailAlertFilter.signals_selection contains the value (boolean).
I would suggest the following:
const matchAlertSignal = (emailList, customAlertList, cryptoSignalList) => {
for (let i of emailList) { //loop through the email list
const emailAlertFilter = customAlertList.filter((customAlertList) => customAlertList.profiles.email === i )
const filterArray = []
const customObject = {}
for(let x of emailAlertFilter) {
customObject.name = x.name
customObject.coins = cryptoSignalList.filter((combo_signal) => x.signals_selection.includes(combo_signal))
filterArray.push(customObject)
}
}
return filterArray
}

How to convert url array query to object in Javascript

I have an URL with query params like this:
myLocalSite/?attributes%5B0%5D%5Bname%5D=customer_property_number&attributes%5B0%5D%5Bop%5D=equal&attributes%5B0%5D%5Bvalue%5D=12&attributes%5B1%5D%5Bname%5D=feedback_tags&attributes%5B1%5D%5Bop%5D=in&attributes%5B1%5D%5Bvalue%5D=test+1%2Cwww
after JSON parsing it convert into next structure
{
attributes[0][name]: "customer_property_number"
attributes[0][op]: "equal"
attributes[0][value]: "12"
attributes[1][name]: "feedback_tags"
attributes[1][op]: "in"
attributes[1][value]: "test 1,www"
}
In the end, I need an array that look like this:
attributes = [
{
name: 'customer_property_number',
op: 'equal',
value: '12',
},
{
name: 'feedback_tags',
op: 'in',
value: 'test 1, www',
},
]
Now does anyone know how I can then put these items into attributes array?
Thanks!
Here is the approach using URLSearchParams and going over each search param, parse and push to array of objects.
var sp = new URLSearchParams(
"myLocalSite/?attributes%5B0%5D%5Bname%5D=customer_property_number&attributes%5B0%5D%5Bop%5D=equal&attributes%5B0%5D%5Bvalue%5D=12&attributes%5B1%5D%5Bname%5D=feedback_tags&attributes%5B1%5D%5Bop%5D=in&attributes%5B1%5D%5Bvalue%5D=test+1%2Cwww"
);
var attributes = [];
for (entry of sp) {
const [attr, value] = entry;
const [index, key] = attr
.split("[")
.filter(x => x.includes("]"))
.map(x => x.slice(0, -1));
if (!attributes[Number(index)]) {
attributes[Number(index)] = {};
}
attributes[Number(index)][key] = value;
}
console.log(attributes);

Get unique keys only from javascript array, where keys and value both are dynamic

This is my object-
[{"index":"style_bags","name":"24"},
{"index":"style_bags","name":"25"},
{"index":"style_bags","name":"26"},
{"index":"category_gear","name":"90"},
{"index":"category_gear","name":"98"},
{"index":"price","name":"400-"}]
This is expected -
[{"index":"style_bags","name":"26"},
{"index":"category_gear","name":"98"},
{"index":"price","name":"400-"}]
Requirement is to get last value and key pair from object in javascript.
As per asked from Certain Performance The way I reached here was through this code -
if(href.indexOf("&") >= 0){
var hrefSplit = href.split('&');
}
if(!(href.indexOf("&") >= 0)){
var hrefSplit = href.split('?');
var hrefSplit2 = hrefSplit[1].split('=');
}
params.push({ index: hrefSplit2[0], name: hrefSplit2[1]});
var i = 0;
jquery.each(params, function( index, value ) {
var key = value.index;
if(hrefSplit2[0] == key){
i++;
}
});
valueGet.push({ index: hrefSplit2[0], name: hrefSplit2[1]});
I am not a javascript pro, so was kind of blank on how to proceed further.
I will make a temp object storing the last found values and then create the resulting array.
let tempObj = {}
let srcArray = [
{"index":"style_bags","name":"24"},
{"index":"style_bags","name":"25"},
{"index":"style_bags","name":"26"},
{"index":"category_gear","name":"90"},
{"index":"category_gear","name":"98"},
{"index":"price","name":"400-"}];
for (let item of srcArray) {
tempObj[item.index] = item.name
}
let result = Object.keys(tempObj).map(index => {
return {
index,
name: tempObj[index]
}
});
console.log(result)
You can use reduce to create an object and then Object.values to get array of values. It will get last object based on index property.
const data = [{"index":"style_bags","name":"24"}, {"index":"style_bags","name":"25"}, {"index":"style_bags","name":"26"}, {"index":"category_gear","name":"90"}, {"index":"category_gear","name":"98"}, {"index":"price","name":"400-"}]
const result = data.reduce((r, e) => Object.assign(r, {[e.index]: e}), {})
console.log(Object.values(result))
You could use a Map and collect the last object with the same index property.
var array = [{ index: "style_bags", name: "24" }, { index: "style_bags", name: "25" }, { index: "style_bags", name: "26" }, { index: "category_gear", name: "90" }, { index: "category_gear", name: "98" }, { index: "price", name: "400-" }],
result = [...new Map(array.map(o => [o.index, o])).values()];
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You inspired me to update my javascript linq library to support .last(). So, using this library, you could:
var list = [{"index":"style_bags","name":"24"},
{"index":"style_bags","name":"25"},
{"index":"style_bags","name":"26"},
{"index":"category_gear","name":"90"},
{"index":"category_gear","name":"98"},
{"index":"price","name":"400-"}];
var filtered = loq(list).groupBy(x => x.index).select(g => g.last());
console.log(filtered.toArray());
<script src="https://cdn.rawgit.com/biggyspender/loq/cb4e5cb4/lib/loq.min.js"></script>

Compare an array of objects to another array of objects

I have two arrays:
myFriends = [ 0: { uid: 123abc }, 1: { uid:456def }, ];
theirFriends = [ 0: { uid: 123abc }, 1: { uid:789ghi }];
Now I want to see if the theirFriends array has an object with the same uid as as an object in the myFriends array and if it does, then set theirFriends[object].isFriend = true; if it doesn't, then set it to false instead.
so it should run through and ultimately set theirFriends[0].isFriend = true. and theirFriends[1].isFriend = false
So the new theirFriends array should be:
theirFriends = [ 0: { uid: 123abc, isFriend: true }, 1: { uid: 789ghi, isFriend: false }];
I have tried: .some(), .map(), .filter(), .forEach(), but I have yet to find a solution that works, but doesn't continously run everytime the object is updated with the new value.
First, you can convert your friend's list to a Set. Sets contain only unique values and it's fast to check if a value is included. Then, you can map over theirFriends and add the new property.
const myFriendSet = new Set(myFriends.map( friend => friend.uid ))
theirFriends = theirFriends.map( friend => ({
uid: friend.uid,
isFriend: myFriendSet.has(friend.uid)
})
hi this is what i came up with
var myF = [ { uid: "123abc" }, { uid: "456def" } ];
var theirF = [ { uid: "123abc" }, { uid: "789ghi" }]
//loop through all their friends
for(var i = 0; i < theirF.length; i++)
{
//loop through all my friends for comparison
for(var j = 0; j < myF.length; j++)
{
if(!theirF[i].isFriend) //if isFriend is not set
theirF[i].isFriend = theirF[i].uid == myF[j].uid; //set current theirFriend isFriend propery
}
}
Lodash _.isEqual is great for comparing objects.
Here is the oneliner using forEach and some:
theirFriends.forEach(tf => tf.isFriend = myFriends.some(mf => mf.uid === tf.uid));
Example:
myFriends = [{uid: '123abc'}, {uid:'456def'}, {uid: '789abc'}, {uid:'789def'}];
theirFriends = [{uid: '123abc'}, {uid:'789ghi'}, {uid: '789def'}, {uid:'000ert'}];
theirFriends.forEach(tf => tf.isFriend = myFriends.some(mf => mf.uid === tf.uid));
console.log(theirFriends);

Javascript using filter/includes on an array of objects

What is the best way to filter out data that exists within an object?
I was able to do use the below code when data was just an array of values but now I need to filter out any data where the item.QID exists in my array of objects.
Data Obj:
var data = [{
QID: 'ABC123',
Name: 'Joe'
},
{
QID: 'DEF456',
Name: 'Bob
}]
Snippet:
// I don't want to include data if this QID is in my object
this.employees = emp.filter(item =>!this.data.includes(item.QID));
From what I understand, includes only works on an array so I need to treat all of the QID values in my object as an array.
Desired Outcome: (assuming item.QID = ABC123)
this.employees = emp.filter(item =>!this.data.includes('ABC123'));
Result:
var data = [{
QID: 'DEF456',
Name: 'Bob'
}]
UPDATE:
Apologies, I left some things a little unclear trying to only include the necessary stuff.
// People Search
this.peopleSearchSub = this.typeahead
.distinctUntilChanged()
.debounceTime(200)
.switchMap(term => this._mapsService.loadEmployees(term))
.subscribe(emp => {
// Exclude all of the current owners
this.employees = emp.filter((item) => item.QID !== this.data.QID);
}, (err) => {
this.employees = [];
});
The above code is what I am working with. data is an object of users I want to exclude from my type-ahead results by filtering them out.
The question is a little ambiguous, but my understanding (correct me if I'm wrong), is that you want to remove all items from a list emp that have the same QID as any item in another list data?
If that's the case, try:
this.employees = emp.filter(item => !this.data.some(d => d.QID === item.QID))
some is an array method that returns true if it's callback is true for any of the arrays elements. So in this case, some(d => d.QID === item.QID) would be true if ANY of the elements of the list data have the same QID as item.
Try Object#hasOwnProperty()
this.employees = emp.filter(item =>item.hasOwnProperty('QID'));
You can use a for ... in to loop through and filter out what you want:
const data = [{
QID: 'ABC123',
Name: 'Joe'
},
{
QID: 'DEF456',
Name: 'Bob'
}]
let newData = [];
let filterValue = 'ABC123';
for (let value in data) {
if (data[value].QID !== filterValue) {
newData.push(data[value]);
}
}
newData will be your new filtered array in this case
You can use an es6 .filter for that. I also added a couple of elements showing the filtered list and an input to allow changing of the filtered value. This list will update on the click of the button.
const data = [{
QID: 'ABC123',
Name: 'Joe'
},
{
QID: 'DEF456',
Name: 'Bob'
}]
displayData(data);
function displayData(arr) {
let str = '';
document.getElementById('filterList').innerHTML = '';
arr.forEach((i) => { str += "<li>" + i.QID + ": " + i.Name + "</li>"})
document.getElementById('filterList').innerHTML = str;
}
function filterData() {
let filterValue = document.getElementById('filterInput').value;
filterText (filterValue);
}
function filterText (filterValue) {
let newArr = data.filter((n) => n.QID !== filterValue);
displayData(newArr)
}
<input id="filterInput" type="text" value="ABC123" />
<button type ="button" onclick="filterData()">Filter</button>
<hr/>
<ul id="filterList"><ul>

Categories