Compare array of objects by property with key of another object - javascript

I want to compare the data.examples array object name.value property value with wcObject.notCoveredList key, If the key matches I want to push all matched values of wcObject to an array inorder to display in UI. If the key doesn't match, I want the name.desc property value of data.examples array object to be pushed by removing the not covered text at the end.
data = {
examples : [
{
name: {
value:"someOne",
desc: "some random word not covered"
},
type: {
value:"General",
desc:"General"
}
}, {
name: {
value:"secondOne",
desc: "second on in the queue not covered"
},
type: {
value:"General",
desc:"General"
}
}, {
name: {
value:"thirdOne",
desc: "third one from the last not covered"
},
type: {
value:"General",
desc:"General"
}
}
]
}
wcObject = {
notCoveredList : [
{ someOne: "anyone can start " },
{ secondOne: "second One cannot start" },
{ thirdOne: "third One can be allowed" }
]
}

So, this code:
Builds up a filter object. We grab all the keys of
wcObject.notCoveredList, and make them keys on a single object (with
an undefined value), so that we can look up those keys with a single
hasOwnProperty() call instead of iterating over an array when we need to filter.
Maps every member of the data.examples array to either its own name.desc property or [stripped of ' not covered'] name.value property.
.
wcNotCoveredKeys = wcObject.notCoveredList.reduce((memo, item) => {
// value is empty for all, we only care about keys.
memo[Object.keys(item)[0]] = undefined;
return memo;
}, {})
// having built up our lookup table of those not covered, we continue:
forUI = data.examples.map(example => {
if (wcNotCoveredKeys.hasOwnProperty(example.name.value)) {
return example.name.value;
}
else {
notCoveredString = example.name.desc;
cutOutIndex = notCoveredString.indexOf(' not covered');
return notCoveredString.slice(0, cutOutIndex)
}
});
(updated to integrate string slicing)
Just to be clear: if you removed the second item from wcObject.notCoveredList, then the output you'd get in forUI (given the example data structures/values you provided) would be
["someOne", "second on in the queue", "thirdOne"]

Related

how to map array having keys and values pairs dynamically added

Hy, My Question is how we can map an array in react js in which the array has key-value pairs but these key values are dynamically added to the array . I mean I don't know what next key-value pair would come in an array.
example below
var array = [{ name: "kamran", age: 25 }, { dev: "kamran", hellow: "kamran" }, { "unknown key will be add dynamically": "unknown value to that key will be add dynamically" }];
for (var i = 0; i < array.length; i++) {
console.log(tifOptions[i]);
}
I want to show it on the table with keys and values using the map function. but the situation is data is coming from a rest API every time it gives me a different array of objects how could I show it will key and value I need to add to the project. because I don't know what key and value will come in the next API request
like below
first request from same API
[
{
'name':"kamran",
'age':25,
},
{
'dev':"js",
'db':"mongo",
},
];
second request from same API
[
{
'name':"kamran",
'age':25,
},
{
'dev':"js",
'db':"mongo",
},
{
'job':"student",
"salary":20000,
}
];
third request from same API
[
{
'name':"kamran",
'age':25,
},
{
'dev':"js",
'db':"mongo",
},
{
'job':"student",
"salary":20000,
},
{
' unknown key will be added':"unknown value will be added",
' unknown key will be added':"unknown value will be added",
}
];
and it goes on every time different key values how could I show this type of data on table with keys and value bcz I don't know in the next request what key value paire would come.
From my understanding of your question, you are going to do something with the key & value pairs coming from the API.
var array = [{ name: "kamran", age: 25 }, { dev: "kamran", hellow: "kamran" }, { "unknown key will be add dynamically": "unknown value to that key will be add dynamically" }];
array.map(item => {
var keys = Object.keys(item);
var obj= {};
keys.forEach(key => {
console.log("key : " ,key, "value : ", item[key])
// do some logic here
obj[key] = item[key];
})
return obj;
}))}
Live link here : https://codesandbox.io/s/youthful-lewin-pgyu8u?file=/src/App.js
I think the answer pretty obvious if you do some googling
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
The function simply let you map a new array base on your base array no matter what element is in it

Finding value in json array and replacing it using Typscript [duplicate]

This question already has answers here:
Find object by id in an array of JavaScript objects
(36 answers)
Closed 2 years ago.
I have a file with 1000s of json rows like below. Im having difficulties locating a specific key in the array.
example json:
{"connection":"98374"
,"db":"8",
,"timestamp":"159905411631"
,"event":"DataCatch"
,"data":[{"key":"ruleid","value":"111"}
,{"key":"responseid","value":"155-response-4"}
,{"key":"responsetype","value":"Capture"}
,{"key":"reason","value":"ClientVisit"}
,{"key":"subreason","value":""}
,{"key":"score","value":"0.00"}
,{"key":"comment","value":""}]
}
I need to be able to find the "reason" key in the "data" array and replace the "value" with "test". The "data" array doesn't always appear on every json row, only when the "event" "dataCatch" is present.
I can parse it into a variable but I can only call the "data" array as a whole. Any ideas how to target specific values in an array?
Having a little trouble with this in Typescript.
There are any number of ways to go about this, but here's one.
First, parse your JSON into an array of objects.
Each element of the array will then look something like this:
{
connection: '98374',
db: '8',
timestamp: '159905411631'
event: 'DataCatch',
data: [
{ key: 'ruleid', value: '111' },
{ key: 'responseid', value: '155-response-4' },
{ key: 'responsetype', value: 'Capture' },
{ key: 'reason', value: 'ClientVisit' },
{ key: 'subreason', value: '' },
{ key: 'score', value: '0.00' },
{ key: 'comment', value: '' },
],
}
Let's call our array of objects allData, so we can refer to it later.
Now we can begin our "surgery".
We'll work from the inside-out, first looking at what needs to be done to a specific entry in an element's data array.
Here's a function that will do just what we need:
function updateReason(entry) {
if (entry.key === 'reason') {
return { ...entry, value: 'test' };
} else {
return entry;
}
}
This function checks if the provided entry has a key with a value of 'reason', and -- if so -- returns a new entry that is identical to the provided one except its value is 'test'.
How can we use this to update an entire data array (in an entry that has data, that is)?
We simply delegate the work to our dear friend map:
function updateData(data) {
// or simply `data.map(updateEntry);`
return data.map(entry => updateEntry(entry));
}
We're slowly working our way "outwards".
What about updating an entire entry in our big allData array (which may or may not contain data)?
// I've called such an entry a "collection", because I already used the name
// "entry" above :(
// A "collection" is just an entry in the big `allData` array.
function updateCollection(collection) {
if (collection.event === 'DataCatch') {
return {
...collection, // Leave everything else the way it is
data: updateData(collection.data), // But update the `data` array
};
} else {
return collection;
}
}
So close.
The last thing we need to do is apply this transformation to every element of our parsed allData array:
// or `allData.map(updateCollection);`
const updatedData = allData.map(collection => updateCollection(collection));
Also:
Q: Wouldn't it be cheaper to mutate the entry?
A: It would be cheaper, but not that much cheaper, due to a large amount of "structural sharing" that occurs here. I would recommend this approach unless you either need to mutate your input for some reason, or performance requirements demand it.
You need to map over the data key in your data variable like this.
data.data = data.data.map((item) => {
if (item.key === "reason") {
item.value = "test";
}
return item;
});
the data key is an array of values, so you need to loop through it and compare the value of the key property to the value you are looking for, if it matches then you can update the value property
https://codesandbox.io/s/angry-shirley-1gh83?file=/src/index.ts:666-782

Recursively adding and removing values from javascript object

So I'm building a basic facet search in React using data from an API, but I'm struggling with the adding & removing of values from the payload sent back to the server. The payload object can contain Arrays, Objects & Strings. So say I have a payload structure like the following:
payload = {
search_query: ""
topic: [],
genre: [],
rating: "",
type: {}
}
Using deepmerge I'm able to pass multiple values back to the API which is working fine, so an example payload would be...
payload = {
search_query: "Luther"
topic: ["9832748273", "4823794872394"],
genre: ["3827487483", "3287483274873"],
rating: "18",
type: {
args: {
when: "today",
min: 15
},
name: "spot"
}
}
So far so good, I get the expected results back. Now I have a toggle on the facet to remove it from the payload, which sends back the value to a function to remove from the payload. For example:
Clear Search, value to remove = "Luther"
Toggle of topic, value to remove = "9832748273"
Toggle of genre, value to remove = "3827487483"
Toggle of rating, value to remove = "18"
Toggle of type, value to remove = { args: { when: "today", min: 15}, name: "spot"}
Search & Rating would return empty strings, topic & genre would remove items from the arrays and type would return an empty object.
This works for removing the array values but feels dirty and I want a clean way to handle all types!
const removeObjValue = (obj, filterValue) => {
Object.entries(obj).forEach(([key, value]) => {
Object.entries(value).forEach(([subKey, subValue]) => {
if(subvalue === filterValue) {
if(Array.isArray(value)) {
const index = value.indexOf(subvalue);
if (index > -1) {
value.splice(index, 1);
}
}
}
});
});
return obj;
}
I just use delete keyword to remove object attributes, like this
if (payload[key]) {
if (payload[key] instanceof Array) {
var idx = payload[key].indexOf(value);
if (idx > -1) payload[key].splice(idx, 1);
} else {
delete payload[key];
}
}
code example

How to return new array with dynamically populated properties?

So my call returns something like:
data:
{
nameData: 'Test33333',
emailData: email#email.com,
urlLink: link.com
additionalDetails: [
{
field: 'email',
value: 'other#email.com'
},
{
field: 'name',
value: 'name1223'
}
]
}
Now, I want to make a function that would take the passed parameter (data) and make an array of objects, that should look like below. It should be done in more generic way.
Array output expectation:
fullData = [
{
name: 'data_name'
value: 'Test33333'
},
{
name: 'data_email',
value: 'email#email.com'
},
{
name: 'data_url',
value: 'Link.com'
},
extraData: [
//we never know which one will it return
]
];
It should be done in the function, with name, for example:
generateDataFromObj(data)
so
generateDataArrFromObj = (data) => {
//logic here that will map correctly the data
}
How can this be achieved? I am not really proficient with JavaScript, thanks.
Assuming that you keep your data property keys in camelCase this will work for any data you add, not just the data in the example. Here I've used planetLink. It reduces over the object keys using an initial empty array), extracts the new key name from the existing property key, and concatenates each new object to the returned array.
const data = { nameData: 'Test33333', emailData: 'email#email.com', planetLink: 'Mars' };
function generateDataArrFromObj(data) {
const regex = /([a-z]+)[A-Z]/;
// `reduce` over the object keys
return Object.keys(data).reduce((acc, c) => {
// match against the lowercase part of the key value
// and create the new key name `data_x`
const key = `data_${c.match(regex)[1]}`;
return acc.concat({ name: key, value: data[c] });
}, []);
}
console.log(generateDataArrFromObj(data));
Just run a map over the object keys, this will return an array populated by each item, then in the func map runs over each item, build an object like so:
Object.keys(myObj).map(key => {return {name: key, value: myObj[key]}})

Get nested keys via a list of keys to get in sequence

Here is some code I have:
// "iterable" is a Map
iterable.forEach((definition, schemaKey) => {
let keyToGet = schemaKey.split('.');
});
keyToGet contains a list of nested keys I want to get in sorted sequence. That is, if I have a user object,
{
profile: {
name: { full: "Cat Man" }
}
}
And I want to access profile.name.full using ['profile', 'name', full]. Is this possible to get the value using this list of values?
You could do a recursive function that travels down the object if the key is found, finally returning the value if it reaches the end of the array. This returns a -1 if a key is not found:
function getFromArr(obj, arr){
function travelDown(current,index){
if(current.hasOwnProperty(arr[index])){
if(index+1 == arr.length){
return current[arr[index]]
}else{
return travelDown(current[arr[index]], index+1)
}
}else{
return -1;
}
}
return travelDown(obj, 0)
}
var obj ={
profile: {
name: { full: "Cat Man" }
}
}
console.log(getFromArr(obj,["profile", "name", "full"])) // Cat Man
console.log(getFromArr(obj,["profile", "name"])) // {full: "Cat Man"}
console.log(getFromArr(obj,["profile", "name", "nonexistant"])) // -1

Categories