How to Search or Compare values out of array of Objects in Javascript and return based on input - javascript-objects

I have simply iterated through an array of objects. But I have no clue how I should compare the previous object values and display data along with current data. as shown in the image.
My Half solutions:
const dataSet = [{
categoryId: 100,
parentCategoryId: -1,
name: "Business",
keyword: "Money",
},
{
categoryId: 200,
parentCategoryId: -1,
name: "Tutoring",
keyword: "Teaching",
},
{
categoryId: 101,
parentCategoryId: 100,
name: "Accounting",
keyword: "Taxes",
},
{
categoryId: 102,
parentCategoryId: 100,
name: "Taxation",
keyword: "",
},
{
categoryId: 201,
parentCategoryId: 200,
name: "Computer",
keyword: "",
},
{
categoryId: 103,
parentCategoryId: 101,
name: "Corporate Tax",
keyword: "",
},
{
categoryId: 202,
parentCategoryId: 201,
name: "Operating System",
keyword: "",
},
{
categoryId: 109,
parentCategoryId: 101,
name: "Small Business Tax",
keyword: "",
}
]
function solution(X) {
// search your keyword
dataSet.map((item)=>{
console.log("Item List: ", item);
if (X === item.categoryId){
const displayData = `\n\t ParentCategoryId : ${item.parentCategoryId} \n\t Name : ${item.name} \n\t Kewords : ${item.keyword}`;
try{
if(displayData) {
console.log("Your Searched Data:", displayData);
}
}catch (e) {
return console.log ("error:", e);
}
}
})
}
solution(201);

Below method will solve your problem.
function solution(cId){
let result = null;
const getParentNode = function(parentId){
const parentNode = dataSet.find(elm => elm.categoryId === parentId);
if(parentNode && parentNode.keyword === ""){
return getParentNode(parentNode.parentCategoryId);
}
return parentNode;
}
for(let i=0; i<dataSet.length; i++){
if(dataSet[i].categoryId === cId){
if(dataSet[i].keyword === "")
result = {...dataSet[i], keyword: getParentNode(dataSet[i].parentCategoryId).keyword};
else
result = dataSet[i];
break;
}
}
return result;
}

This may probably help you!
var result = result1.filter(function (o1) {
return result2.some(function (o2) {
return o1.id === o2.id; // return the ones with equal id
});
});
// if you want to be more clever...
let result = result1.filter(o1 => result2.some(o2 => o1.id === o2.id));

Related

Adding new chart types to react pivottable

I'm wondering if it's possible to add new type of charts, like a radar chart, to the React library plotly/react-pivottable https://github.com/plotly/react-pivottable.
I would like to add a spider chart, always from the chart library plotly, but I can't understand where to start as the documentation is a litle poor and the GitHub repo is quite silence...
Maybe it's not even possible.
Does anyone know if it's possible?
Yes, it's completely possible to add custom charts. You need to copy makeRenderer function from original repo and customised it according to the chart types.
To add a new chart type (radar chart), to React Pivottable, you've to add directly on PlotlyRenderers.
Here's an example of how you could add a radar chart to React Pivottable:
const Plot = createPlotlyComponent(window.Plotly);
const PlotlyRenderers = createPlotlyRenderers(Plot);
const makeRenderer = (
PlotlyComponent,
traceOptions = {},
layoutOptions = {},
transpose = false
) {
class Renderer extends React.PureComponent {
render() {
const pivotData = new PivotData(this.props);
const rowKeys = pivotData.getRowKeys();
const colKeys = pivotData.getColKeys();
const traceKeys = transpose ? colKeys : rowKeys;
if (traceKeys.length === 0) {
traceKeys.push([]);
}
const datumKeys = transpose ? rowKeys : colKeys;
if (datumKeys.length === 0) {
datumKeys.push([]);
}
let fullAggName = this.props.aggregatorName;
const numInputs =
this.props.aggregators[fullAggName]([])().numInputs || 0;
if (numInputs !== 0) {
fullAggName += ` of ${this.props.vals.slice(0, numInputs).join(", ")}`;
}
const data = traceKeys.map((traceKey) => {
const r = [];
const theta = [];
for (const datumKey of datumKeys) {
const val = parseFloat(
pivotData
.getAggregator(
transpose ? datumKey : traceKey,
transpose ? traceKey : datumKey
)
.value()
);
r.push(isFinite(val) ? val : null);
theta.push(datumKey.join("-") || " ");
}
const trace = { name: traceKey.join("-") || fullAggName };
trace.fill = "toself";
trace.r = r;
trace.theta = theta.length > 1 ? theta : [fullAggName];
return Object.assign(trace, traceOptions);
});
const layout = {
polar: {
radialaxis: {
visible: true,
range: [0, 50]
}
},
/* eslint-disable no-magic-numbers */
// width: window.innerWidth / 1.5,
// height: window.innerHeight / 1.4 - 50
// /* eslint-enable no-magic-numbers */
};
return (
<PlotlyComponent
data={data}
layout={Object.assign(
layout,
layoutOptions,
this.props.plotlyOptions
)}
config={this.props.plotlyConfig}
onUpdate={this.props.onRendererUpdate}
/>
);
}
}
return Renderer;
}
const radarChart = () => {
return makeRenderer(
Plot,
{ type: "scatterpolar" },
{},
true
);
}
PlotlyRenderers["Radar Chart"] = radarChart({});
const data = [
{
country: "Spain",
name: "Santiago",
surname: "Ramón y Cajal",
sex: "Male",
age: 57,
subject: "Medicine"
},
{
country: "United Kingdom",
name: "Ada",
surname: "Lovelace",
sex: "Female",
age: 47,
subject: "Computing"
},
{
country: "United Kingdom",
name: "Alan",
surname: "Turing",
sex: "Male",
age: 55,
subject: "Computing"
},
{
country: "France",
name: "Antoine",
surname: "Lavoisier",
sex: "Male",
age: 12,
subject: "Chemistry"
},
{
country: "Poland",
name: "Marie",
surname: "Curie",
sex: "Female",
age: 33,
subject: "Chemistry"
},
{
country: "Austria",
name: "Hedy",
surname: "Lamarr",
sex: "Female",
age: 34,
subject: "Computing"
},
{
country: "Austria",
name: "Erwin",
surname: "Schrödinger",
sex: "Male",
age: 38,
subject: "Physics"
}
];
export default function App() {
const [opts, setOpts] = useState({});
return (
<div className="App">
<PivotTableUI
data={data}
onChange={(e) => {
setOpts(e);
console.log(e);
}}
renderers={Object.assign({}, TableRenderers, PlotlyRenderers)}
cols={["sex"]}
rows={["subject", "country"]}
rendererName="Table Heatmap"
aggregatorName="Average"
vals={["age"]}
derivedAttributes={{ completeName: (el) => el.name + " " + el.surname }}
{...opts}
/>
</div>
);
}
Here is the complete code:
https://codesandbox.io/s/react-pivot-table-custom-charts-2utqbt?file=/src/App.js:3511-4468

REACT: Updating nested state

I have two sets of data. Both are saved in a states.I want to update the rowsData inside the data1 state based on the values in data2 state. The "row" value in the data2 object refers to the "id" of rowsData in the data1 state and columns in the data2 refers to any data beside id in the rowsData object in data1. I want to pick "row" and "column" from data2 and cahnge the respective data inside rowsData in data1.
let tableData = {
columnsDef: [
{ title: "id",field: "id",className: "header-style" },
{ title: "First_name", field: "First_name", className: "header-style" },
{ title: "Last_name", field: "Last_name", className: "header-style" },
{ title: "Email", field: "Email", className: "header-style" },
],
rowsData:[
{ id: "1", First_name: "Donald", Last_name: "OConnell", Email: "DOCONNEL" },
{ id: "2", First_name: "Douglas", Last_name: "Grant", Email: "DGRANT" },
{ id: "3", First_name: "Jennifer", Last_name: "Whalen", Email: "JWHALEN" },
{ id: "4", First_name: "Michael", Last_name: "Hartstein", Email: "MHARTSTE" },
{ id: "5", First_name: "Pat", Last_name: "Fay", Email: "PFAY" },
{ id: "6", First_name: "Susan", Last_name: "Mavris", Email: "SMAVRIS" },
{ id: "7", First_name: "Hermann", Last_name: "Baer", Email: "HBAER" }
],
file: [
{ file: { path: "dummy_data_3 .csv"}}
],
}
let updatedTableData = [
{ "row": 2, "column": "Email", "oldValue": "DGRANT", "newValue": "DGRANT UPDATED" },
{ "row": 6, "column": "First_name", "oldValue": "Susan", "newValue": "SUSAN UPDATED" },
{ "row": 4, "column": "Last_name", "oldValue": "Hartstein", "newValue": "Hartstein UPDATED" }
]
const [data1, setData1] = useState(tableData)
const [data2, setData2] = useState(updatedTableData)
Here is the codesandbox link for the issue.
https://codesandbox.io/s/reverent-firefly-r87huj?file=/src/App.js
You can follow these steps for updating data1 from handleAppyChanges function:
Create a copy of rowsData:
const td = [...data1.rowsData];
Iterate over data2 and find related item, then update its related column:
data2.forEach((item) => {
let row = data1.rowsData.find((r) => r.id === item.row);
if (row) {
let index = data1.rowsData.findIndex((v) => v === row);
row[item.column] = item.newValue;
td[index] = row;
}
});
Update table data via state:
const newData = {
file: data1.file,
rowsData: td,
columnDef: data1.columnsDef
};
setData1(newData);
Here's the full function:
const handleAppyChanges = () => {
const td = [...data1.rowsData];
data2.forEach((item) => {
let row = data1.rowsData.find((r) => r.id === item.row);
if (row) {
let index = data1.rowsData.findIndex((v) => v === row);
row[item.column] = item.newValue;
td[index] = row;
}
});
const newData = {
file: data1.file,
rowsData: td,
columnDef: data1.columnsDef
};
setData1(newData);
console.log("Updated Data 1: ", td);
};
You can access the full code via codesandbox:
Apply into onChange and check it.
const handleAppyChanges = () => {
data2.map((item) => {
data1.rowsData.map((data) => {
//match both id and row
if (data.id == item.row) {
//check column is there or not
let column = data.hasOwnProperty(item.column);
if (column) {
//if yes then change the value
data[item.column] = item.newValue;
}
}
});
});
setData1({ ...data1 });
};

Get a specific item length in array object [nodejs]

I want to get the length of an array that match the value specified by the condition.
var school = {
student : {
name: Json,
class: 0,
type: male,
average: B+
},
student : {
name: Afrado,
class: 0,
type: male,
average: C+
},
student : {
name: Emily,
class: 1,
type: female,
average: A+
}
};
I'd like to know the lengh of class "0"
but I don't know how to resolve this case?
In this case I can get the length of "2" for my results.
Have a nice day~ :)
Your array is not structured properly, what you need to do is to filter and get the length of the filtered items.
var school = [
{
name: "Json",
class: 0,
type: "male",
average: "B+"
},
{
name: "Afrado",
class: 0,
type: "male",
average: "C+"
},
{
name: "Emily",
class: "1",
type: "female",
average: "A+"
}
];
console.log(school.filter(student => student.class === 0).length);
You can use the reduce function to avoid creating a temporary array with filter.
console.log(school.reduce((count, student) => student.class === 0 ? ++count : count, 0));
you can also use this way:
var school = [
{
name: "Json",
class: 0,
type: "male",
average: "B+"
},
{
name: "Afrado",
class: 0,
type: "male",
average: "C+"
},
{
name: "Emily",
class: "1",
type: "female",
average: "A+"
}
];
function search(className, myArray){
var countClass = 0;
for (var i=0; i < myArray.length; i++) {
if (myArray[i].class === className) {
countClass++;
}
}
return countClass;
}
function searchForeach(className, myArray){
var countClass = 0;
myArray.forEach((item) => {
if (item.class === className) {
countClass++;
}
});
return countClass;
}
function searchFind(className, myArray){
var countClass = 0;
myArray.find((item, index) => {
if (item.class === className) {
countClass++;
}
});
return countClass;
}
console.log(search(0, school));
console.log(searchForeach("1", school));
console.log(searchFind(0, school));
second way use find:

I want to insert the data into an array but it shows a warning message that duplicates are not allowed

$scope.data = {
"items": [{
id: 1,
name: "Vijay",
email: "vijay#gmail.com",
mobile: "9090909090",
salary: 98690
}, {
id: 2,
name: "ajay",
email: "ajay#gmail.com",
mobile: "9190909090",
salary: 98969
}, {
id: 3,
name: "mahesh",
email: "mahesh#gmail.com",
mobile: "8090909090",
salary: 78555
}, {
id: 4,
name: "ganesh",
email: "ganesh#gmail.com",
mobile: "9099909090",
salary: 48756
}, {
id: 5,
name: "balu",
email: "balu#gmail.com",
mobile: "9880909090",
salary: 98909
}, {
id: 6,
name: "kapil",
email: "kapil#gmail.com",
mobile: "9090907790",
salary: 76595
}]
}
$scope.items = $scope.data.items;
$scope.addItem = function(item) {
$scope.items.filter(function(el) {
if (el.id !== item.id) {
console.log(el.id, "xxxxxxxxxxxx inside if xxxxxxxxxxx", item.id);
$scope.items.push(item);
// console.log($scope.items,item);
$scope.item = {};
} else {
console.log("sdhjkkkkk inside else kkkkkkkkkkkkkkk")
alert("already exist");
}
});
It's because you trying to push element on each iteration of 'filter' loop if id of your item !== item id of array element.
Also, filter is not what you need for this. It returns new array.
You can use 'every' for this. For example:
$scope.addItem = function(item) {
if (checkEquality(item, $scope.items)) {
$scope.items.push(item);
}
};
function checkEquality(element, array) {
return array.every(function(item) {
return item.id !== element.id;
});
}

Filter an Array based on multiple values

I have the following simple JSON array:
const personList = [
{
id: 1,
name: "Phil"
},
{
id: 2,
name: "Bren"
},
{
id: 3,
name: "Francis Underwood"
},
{
id: 4,
name: "Claire Underwood"
},
{
id: 5,
name: "Ricky Underwood"
},
{
id: 6,
name: "Leo Boykewich"
}
];
And I would like to filter this by passing an array of ids so something like [1,4] would be passed in and it would only return "Phill" and "Claire Underwood"
This is what the function looks like but I know it's wrong attendeeIds is an array that's passed in [1, 4]:
getAttendeesForEvent: (attendeeIds) => {
if (attendeeIds === undefined) return Promise.reject("No attendee id provided");
return Promise.resolve(personList.filter(x => x.id == [attendeeIds]).shift());
}
I haven't used JS in years. I've looked for examples but they all seem too complex for what I'm trying to achieve. So how can I filter this based on an array of id's passed in?
return Promise.resolve(personList.filter(x => attendeeIds.indexOf(x.id) !== -1));
You want to check if the id of each item your looping over exists inside of attendeeIds. Use Array.indexOf inside of the filter to do that.
This will return an array of { id: #, name: String } objects.
If you want to return just the names of those objects, you can do a map afterwards which will transform an array into another array using the function that you provide.
const filteredNames = personList
.filter(x => attendeeIds.indexOf(x.id) !== -1)
.map(x => x.name);
// ['Phil', 'Claire Underwood']
You could do something in these lines. Hope this helps.
const personList = [{
id: 1,
name: "Phil"
}, {
id: 2,
name: "Bren"
}, {
id: 3,
name: "Francis Underwood"
}, {
id: 4,
name: "Claire Underwood"
}, {
id: 5,
name: "Ricky Underwood"
}, {
id: 6,
name: "Leo Boykewich"
}];
let attendeeIds = [1, 5];
let getAttendeesForEvent = () => {
return new Promise(function(resolve, reject) {
if (attendeeIds === undefined) {
reject("No attendee id provided");
} else {
resolve(personList.filter((x) => attendeeIds.includes(x.id)).map((obj) => obj.name));
}
});
}
getAttendeesForEvent().then((data) => console.log(data))

Resources