React.js: How to compare data from 2 objects of arrays? - javascript

I have an array of objects displayed on the UI. Now I want to change the style of the data which doesn't match with the data from another array of objects.
Basically my goal is to create a boolean data which checks if the data are matching for both array of objects, and according to this boolean data the style will be changed.
Here is what I have.
And codesandbox link
import React from "react";
import "./styles.css";
const result1 = [
{ id: 1, name: "Sandra", type: "user", username: "sandra" },
{ id: 2, name: "John", type: "admin", username: "johnny2" },
{ id: 3, name: "Peter", type: "user", username: "pete" },
{ id: 4, name: "Bobby", type: "user", username: "be_bob" },
{ id: 5, name: "Bob", type: "user", username: "bob" },
{ id: 6, name: "James", type: "user", username: "james" },
{ id: 7, name: "Bill", type: "user", username: "bill" }
];
const result2 = [
{ id: 2, name: "John", username: "johnny2" },
{ id: 5, name: "Bob", type: "user", username: "bob" },
{ id: 4, name: "Bobby", username: "be_bob" }
];
export default function App() {
const excludedPerson = result1.filter(
(person1) => !result2.some((person2) => person1.name === person2.name)
);
console.log(excludedPerson);
return (
<div className="App">
{result1.map((person) => (
<ul key={person.id}>
<div>{person.name}</div>
<div
style={{
textDecoration: "boolean" ? "line-through" : "none" // instead of string it should be a boolean
}}
>
{person.username}
</div>
</ul>
))}
</div>
);
}

Instead of using filter you can use map and get the boolean excludedPerson array
changes:
1) use map instead of filter
const excludedPerson = result1.map(
(person1) => !result2.some((person2) => person1.name === person2.name)
);
2) Add second parameter in JSX i.e index
{result1.map((person, i) => (
3) change CSS styles accordingly: I've strike through the result1 elements that are not in result2
textDecoration: !excludedPerson[i] ? "line-through" : "none"
CODE DEMO
import React from "react";
import "./styles.css";
const result1 = [
{ id: 1, name: "Sandra", type: "user", username: "sandra" },
{ id: 2, name: "John", type: "admin", username: "johnny2" },
{ id: 3, name: "Peter", type: "user", username: "pete" },
{ id: 4, name: "Bobby", type: "user", username: "be_bob" },
{ id: 5, name: "Bob", type: "user", username: "bob" },
{ id: 6, name: "James", type: "user", username: "james" },
{ id: 7, name: "Bill", type: "user", username: "bill" }
];
const result2 = [
{ id: 2, name: "John", username: "johnny2" },
{ id: 5, name: "Bob", type: "user", username: "bob" },
{ id: 4, name: "Bobby", username: "be_bob" }
];
export default function App() {
const excludedPerson = result1.map(
(person1) => !result2.some((person2) => person1.name === person2.name)
);
console.log(excludedPerson);
return (
<div className="App">
{result1.map((person, i) => (
<ul key={person.id}>
<div>{person.name}</div>
<div
style={{
textDecoration: !excludedPerson[i] ? "line-through" : "none" // instead of string it should be a boolean
}}
>
{person.username}
</div>
</ul>
))}
</div>
);
}

Mabye something like this? Return only the common objects in the two array of objects
const result1 = [
{ id: 1, name: 'Sandra', type: 'user', username: 'sandra' },
{ id: 2, name: 'John', type: 'admin', username: 'johnny2' },
{ id: 3, name: 'Peter', type: 'user', username: 'pete' },
{ id: 5, name: 'Bob', type: 'user', username: 'bob' },
{ id: 6, name: 'James', type: 'user', username: 'james' },
{ id: 7, name: 'Bill', type: 'user', username: 'bill' },
];
const result2 = [
{ id: 2, name: 'John', username: 'johnny2' },
{ id: 5, name: 'Bob', type: 'user', username: 'bob' },
{ id: 4, name: 'Bobby', username: 'be_bob' },
];
const output = result1.filter(({ id: id1 }) =>
result2.some(({ id: id2 }) => id2 === id1)
);
console.log(output);

Related

search an item in multidimentionnal array

I'm trying to find an element on a multidimentionnal array usin JAVASCRIPT function, but I get error
This is my array's data:
export const datas = [
{
id: 1,
firstName: 'John',
tables: [
{ ID: 11, title: 'Lorem' },
{ ID: 12, title: 'Ipsum' },
],
},
{
id: 2,
firstName: 'Doe',
tables: [
{
ID: 22,
title: 'Arke',
nodes: [{ name: 'Name1' }, { name: 'Name2' }, { name: 'Name3' }],
},
{ ID: 23, title: 'Korem' },
],
},
{
id: 3,
firstName: 'Brad',
tables: [
{
ID: 30,
title: 'Mern',
nodes: [{ name: 'Name4' }, { name: 'Name5' }, { name: 'Name6' }],
},
{
ID: 31,
title: 'Full',
nodes: [{ name: 'Name7' }, { name: 'Name8' }, { name: 'Name9' }],
},
],
},
];
I've tried a reccursive function but it's not work, this is my code :
export const findById = (arr, id) => {
for (let o of arr) {
if (o.tables.length > 0) {
let a = findById(o.tables.nodes, 'id');
console.log(a);
}
}
};
I want to print the Object with ID 22, the problem is that I don't have the same structure in each dimension, and it still confuse me..
My Input : 22
My output :
{
ID: 22,
title: 'Arke',
nodes: [{ name: 'Name1' }, { name: 'Name2' }, { name: 'Name3' }],
},
Have you an idea how to edit my function to get my input's response ?
Your recursive function wasn't too far off, you need to check if the item as a tables first before recursively calling it again. And then finally just check the ID in the loop.
eg..
const datas=[{id:1,firstName:"John",tables:[{ID:11,title:"Lorem"},{ID:12,title:"Ipsum"}]},{id:2,firstName:"Doe",tables:[{ID:22,title:"Arke",nodes:[{name:"Name1"},{name:"Name2"},{name:"Name3"}]},{ID:23,title:"Korem"}]},{id:3,firstName:"Brad",tables:[{ID:30,title:"Mern",nodes:[{name:"Name4"},{name:"Name5"},{name:"Name6"}]},{ID:31,title:"Full",nodes:[{name:"Name7"},{name:"Name8"},{name:"Name9"}]}]}];
function findById(arr, ID) {
for (const a of arr) {
if (a.tables) {
const r = findById(a.tables, ID);
if (r) return r;
}
if (a.ID === ID) return a;
}
}
console.log(findById(datas, 22));
if you just need the nested data you can use flatMap and find
const findById = (arr, id) =>
arr
.flatMap(d => d.tables)
.find(t => t.ID === id)
const datas = [{
id: 1,
firstName: 'John',
tables: [{
ID: 11,
title: 'Lorem'
},
{
ID: 12,
title: 'Ipsum'
},
],
},
{
id: 2,
firstName: 'Doe',
tables: [{
ID: 22,
title: 'Arke',
nodes: [{
name: 'Name1'
}, {
name: 'Name2'
}, {
name: 'Name3'
}],
},
{
ID: 23,
title: 'Korem'
},
],
},
{
id: 3,
firstName: 'Brad',
tables: [{
ID: 30,
title: 'Mern',
nodes: [{
name: 'Name4'
}, {
name: 'Name5'
}, {
name: 'Name6'
}],
},
{
ID: 31,
title: 'Full',
nodes: [{
name: 'Name7'
}, {
name: 'Name8'
}, {
name: 'Name9'
}],
},
],
},
];
console.log(findById(datas, 22))
js has amazing array options https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
the ones which will help you most are probably:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap
here are some examples
// get the base with id 22
const baseWith22ID = datas.filter(f => f.tables.filter(s => s.id = 22))
// (i guess you want this one) get all elements with id 22
const onlyElementsWith22ID = datas.flatMap(f => f.tables.filter(s => s.id = 22))

How to filter and map an array?

I have this object that I need to filter it.
let data = JSON.parse(this.getDataFromArray).map((x: any) => x.isEnabled === true);
I need to get in "data" only ID's of values that "isEnabled" is true.
Use Array.prototype.flatMap to achieve the result.
const dataArray = [
{ id: 1, name: "Alice", isEnabled: false },
{ id: 2, name: "Bob", isEnabled: true },
{ id: 3, name: "Charlie", isEnabled: true },
{ id: 4, name: "Dave", isEnabled: true },
{ id: 5, name: "Eve", isEnabled: false },
{ id: 6, name: "Frank", isEnabled: false },
];
let data = dataArray.flatMap(elm => elm.isEnabled ? [elm.id]: []);
console.log(data);
Please note that flatMap cannot be used in IE without a polyfill.
If you need IE support, use Array.prototype.forEach
const dataArray = [
{ id: 1, name: "Alice", isEnabled: false },
{ id: 2, name: "Bob", isEnabled: true },
{ id: 3, name: "Charlie", isEnabled: true },
{ id: 4, name: "Dave", isEnabled: true },
{ id: 5, name: "Eve", isEnabled: false },
{ id: 6, name: "Frank", isEnabled: false },
];
let data = [];
dataArray.forEach((elm) => {
if (elm.isEnabled) {
data.push(elm.id);
}
});
console.log(data);
Try this to filter first, and map to desired property:
JSON.parse(this.getDataFromArray).filter((x: any) => x.isEnabled === true).map((result: any) => result.id);

How can I filter an array with an array of strings

I am running into an issue, I have a similar array of Strings in JS:
const users = [
{
age: 13,
username: "adam",
interests: []
},
{
age: 20,
username: "eve"
interests: [
{
name: "Bars",
},
{
name: "Cafe",
},
],
},
{
age: 23,
username: "alex"
interests: [
{
name: "Bars",
},
{
name: "Healthy",
},
{
name: "Japanese",
},
],
},
];
const interests = ["Bars", "Cafe"];
And I would like to filter users having the same interests as the array of interests.
I tried in different ways without getting the desired result. How should I proceed with this?
Depending on the wanted result with users with at least one matching interest or all wanted interests, you could take either Array#some or Array#every for filtering interests.
const
users = [{ age: 13, username: "adam", interests: [] }, { age: 20, username: "eve", interests: [{ name: "Bars" }, { name: "Cafe" }] }, { age: 23, username: "alex", interests: [{ name: "Bars" }, { name: "Healthy" }, { name: "Japanese" }] }],
interests = ["Bars", "Cafe"],
one = users.filter(o => interests.some(i => o.interests.some(({ name }) => name === i))),
all = users.filter(o => interests.every(i => o.interests.some(({ name }) => name === i)));
console.log(one);
console.log(all);
.as-console-wrapper { max-height: 100% !important; top: 0; }
const users = [
{
age: 13,
username: "adam",
interests: []
},
{
age: 20,
username: "eve",
interests: [
{
name: "Bars",
},
{
name: "Cafe",
},
],
},
{
age: 23,
username: "alex",
interests: [
{
name: "Bars",
},
{
name: "Healthy",
},
{
name: "Japanese",
},
],
},
];
const interests = ["Bars", "Cafe"];
function getUsers(users, interests) {
return users.map(user => {
for(let i=0; i<interests.length; i++) {
return user.interests.some(interest => interest.name == interests[i]) ? user : false
}
})
}
console.log(getUsers(users, interests))
const users = [
{
age: 13,
username: "adam",
interests: []
},
{
age: 20,
username: "eve",
interests: [
{
name: "Bars",
},
{
name: "Cafe",
},
],
},
{
age: 23,
username: "alex",
interests: [
{
name: "Bars",
},
{
name: "Healthy",
},
{
name: "Japanese",
},
],
},
];
const interests = ["Bars", "Cafe"];
const filteredData = users.filter(user => {
const userInterests = user.interests.map(interest => interest.name);
return JSON.stringify(userInterests) === JSON.stringify(interests)
} );
console.log('data ->', filteredData);
use below code
users.filter(e=>e.interests.find(q=>interests.some(w=>w==q.name)))
This snippet will return a structure of people with the same interests. The key is the interestName and the value is a array of people.
const users = [
{
age: 13,
username: "adam",
interests: [],
},
{
age: 20,
username: "eve",
interests: [
{
name: "Bars",
},
{
name: "Cafe",
},
],
},
{
age: 23,
username: "alex",
interests: [
{
name: "Bars",
},
{
name: "Healthy",
},
{
name: "Japanese",
},
],
},
];
let commonInterests = new Map();
users.forEach((user) => {
for (let interest in user.interests) {
const username = user.username;
const interestName = user.interests[interest].name;
if (commonInterests.has(interestName)) {
let knownNames = commonInterests.get(interestName);
knownNames.push(username);
commonInterests.set(interestName, knownNames);
} else {
commonInterests.set(interestName, [username]);
}
}
});
console.log(Object.fromEntries([...commonInterests]));

React: bind method on dynamic table generation

I'm currently trying to generate a table that can not only display values as dynamic as possible, but also have functionality that gets passed to a certain column. The draft of the structure is like this:
<Table
dataHeaders={[
{ headerTitle: 'ID', headerKey: 'id', filterable: true },
{ headerTitle: 'First Name', headerKey: 'firstname', filterable: true, sortable: true },
{ headerTitle: 'Last Name', headerKey: 'lastname', filterable: true, sortable: true },
{
headerTitle: 'Details',
text: 'Show details',
functionalColumn: true,
function: row => {
alert(`${row.id}: ${row.firstname} ${row.middlename} ${row.lastname}`);
},
},
{
headerTitle: 'Delete',
text: 'Delete',
functionalColumn: true,
function: row => {
const remainingData = this.state.data.filter(item => item.id !== row.id);
this.setState({ data: remainingData });
},
},
]}
data={[
{ id: 1, firstname: 'Jess', lastname: 'Smith' },
{ id: 2, firstname: 'Alex', lastname: 'Williams' },
{ id: 3, firstname: 'Tayler', lastname: 'Brown' },
{ id: 4, firstname: 'Hannah', lastname: 'Anderson' },
{ id: 5, firstname: 'Anna', lastname: 'Adams' },
{ id: 6, firstname: 'Michael', lastname: 'Johnson' },
{ id: 7, firstname: 'John', lastname: 'Willis' },
{ id: 8, firstname: 'Joey', lastname: 'Sullivan' },
{ id: 9, firstname: 'Chandler', lastname: 'Anderson' },
{ id: 10, firstname: 'Monica', lastname: 'Black' },
{ id: 11, firstname: 'Rachel', lastname: 'Tyson' },
{ id: 12, firstname: 'Alex', lastname: 'Doe' },
]}
/>
Showing the details works completely fine, using this code in the Table component:
<td key={`${metaColumn.text}-${index}`}>
<span className={'Table__delete'} onClick={metaColumn.function.bind(this, row)}>
{metaColumn.text}
</span>
</td>
However, and not surprisingly, manipulating the state of Table doesn't work properly, as apparently binding the method with bind(this, row) isn't sufficient.
Is there a way I can make this.state accessible in this kind of environment?
So, I finally figured out, why it wouldn't work. The reason is quite simple: you cannot change the context of this in arrow functions.
So instead of
function: row => {
const remainingData = this.state.data.filter(item => item.id !== row.id);
this.setState({ data: remainingData });
}
I used:
function(row) {
const remainingData = this.state.data.filter(item => item.id !== row.id);
this.setState({ data: remainingData });
}

How to add object element in array based on condition

I have static array constant of objects something similar to below.
export const EMPLOYEES = [
{
id: 2,
name: ‘John’,
},
{
id: 3,
name: ‘Doe’,
},
{
id: 4,
name: ‘Bull’,
},
{
id: 5,
name: ‘Scott’,
},
];
Now I need to add the last element only based on if some condition is true. Some this like if isAmerican() is true.
Can somebody help me here how to add element based on the condition? Thanks.
You can do it using spread operator:
export const EMPLOYEES = [
{
id: 2,
name: "John",
},
{
id: 3,
name: "Doe",
},
{
id: 4,
name: "Bull",
},
{
id: 5,
name: "Scott",
},
... isAmerican() ? [{ id: 6, name: "Jemmy"}] : []
];
You should never modify (or try to modify) a constant. I can see two ways you can do this:
Create a pure function to return a new constant with the new object added to the array
Use a spread operator in the definition of the constant
Option 1: Pure function
function makeNewArray(array, objectToAppend, isAmerican) {
return isAmerican ? [...array, objectToAppend] : array
}
const EMPLOYEES = [
{
id: 2,
name: "John",
},
{
id: 3,
name: "Doe",
},
{
id: 4,
name: "Bull",
},
{
id: 5,
name: "Scott",
}
];
const arrayWithAmerican = makeNewArray(EMPLOYEES, { id: 6, name: "American Frank"}, true);
const arrayWithoutAmerican = makeNewArray(EMPLOYEES, { id: 6, name: "Not American Frank"}, false);
console.log(arrayWithAmerican);
console.log(arrayWithoutAmerican);
Option 2: Spread operator
function isAmerican(){
// generic code here.
return true;
}
const EMPLOYEES = [
{
id: 2,
name: "John",
},
{
id: 3,
name: "Doe",
},
{
id: 4,
name: "Bull",
},
{
id: 5,
name: "Scott",
},
... isAmerican() ? [{ id: 6, name: "American Frank"}] : []
];
If the condition will be fulfilled, simply push an object to your EMPLOYEES array:
let isAmerican = true;
const EMPLOYEES = [
{
id: 2,
name: "John",
},
{
id: 3,
name: "Doe",
},
{
id: 4,
name: "Bull",
},
{
id: 5,
name: "Scott",
},
];
if(isAmerican) {
EMPLOYEES.push({
id: 6,
name: "Frank"
})
}
console.log(EMPLOYEES)
Fiddle: https://jsfiddle.net/rqx35pLz/

Categories

Resources