Remove an object from an array of if not Present in Array - javascript

I have a project in React. In this Project, I have some array of users stored and I have one more array that contains message objects having three properties from, to, and message. Now I want, if the user id is not present message array then remove the user from the list. I am using Node.js as a backend. Or in simple words if the user has not sent or received any messages, then remove from them from the user list. Or if there any other solution for storing the users and messages in a single array.
users.json
[
{
"id": "1",
"name": "Rampal"
},
{
"id": "2",
"name": "Anisha"
},
{
"id": "3",
"name": "john"
}
]
messages.json
[
{
"from": 1,
"to": 2,
"message": "Please call me"
},
{
"from": 3,
"to": 2,
"message": "Please call me"
}
]
Showusers.js
import React, { useEffect, useState } from "react";
import axios from "axios";
import ShowSingle from "./ShowSingle";
import ShowRecentSingle from "./ShowRecentSingle";
function Showusers() {
const [users, setUsers] = useState();
const [loading, setLoading] = useState(true);
useEffect(() => {
axios
.get("http://localhost:3005/")
.then(function (response) {
setUsers(response.data);
console.log("users" + JSON.stringify(response.data));
setLoading(false);
})
.catch(function (error) {
console.log(error);
setLoading(false);
});
}, []);
return (
<div>
{!loading &&
users.map((user, id) => <ShowRecentSingle key={id} user={user} />)}
<input
type="text"
name="message"
id=""
className="message-input"
placeholder="type new message....."
/>
</div>
);
}
export default Showusers;

Solution with Map
You can maintain a map of active users who either send or receive messages and then filter out inactive users from the array of users with it.
const usersArray = [
{
id: 1,
name: "Rampal"
},
{
id: 2,
name: "Anisha"
},
{
id: 3,
name: "john"
}
];
const messagesArrary = [
{
from: 1,
to: 2,
message: "Please call me"
},
{
from: 3,
to: 2,
message: "Please call me"
}
];
const getActiveUserProfiles = (messages) => {
// map of users who sent or receive messages
const activeUsers = new Map();
messages.forEach(({ to, from }) => {
activeUsers.set(to, to);
activeUsers.set(from, from);
});
// filter out inactive users
return usersArray.filter(({ id }) => activeUsers.get(id));
};
const activeUserProfiles = getActiveUserProfiles(messagesArrary);
console.log(activeUserProfiles);

let users = [
{
"id": "1",
"name": "Rampal"
},
{
"id": "2",
"name": "Anisha"
},
{
"id": "3",
"name": "john"
}
];
let messages = [
{
"from": 1,
"to": 2,
"message": "Please call me"
},
{
"from": 3,
"to": 2,
"message": "Please call me"
}
];
let res = users.map(x => Object.assign(x, messages.find(y => y.from == x.id)));
for (let i = 0; i < res.length; i++) {
if(res[i].from === undefined) {
res.splice(i, 1);
}
}
console.log(res)

Related

Adjust a 22-line JS function that now returns wrong counts with +1 / +2 differences for no reasons

My function further below seems fine yet the count is overstated in some instances, eg: should count '1' but shows '2'.
Data source for context:
{
"currency": "USD",
"services": [
{
"category": [
{"token": "token1"},
{"token": "token2"}
],
"price": 149
},
{
"category": [
{"token": "token3"},
{"token": "token4"}
],
"price": 149
}
]
},
{
"currency": "EUR",
"services": [
{
"category": [
{"token": "token1"},
{"token": "token2"}
],
"price": 149
},
{
"category": [
{"token": "token3"},
{"token": "token4"}
],
"price": 149
}
Goal: COUNT the frequency of category tokens per price, sorted by currency in their own objects.
Desired output schema (for illustration purposes, unrelated to above schema example):
{
"result": [
{
"currency": "USD",
"token": "Wellness",
"count": 1,
"price": 100
},
{
"currency": "USD",
"token": "Adventure",
"count": 1,
"price": 300
}
]
}
It appears that sometimes, the count is not right, by +1 or +2 difference for no apparent reasons.
My function, which outputs wrong counts:
const data = inputs.data;
const result = [];
let error = null;
try {
data.forEach(item => {
item.services.forEach(service => {
service.category.forEach(tokenObject => {
const token = tokenObject.token;
const existingToken = result.find(item => item.token === token && item.price === service.price && item.currency === item.currency);
if (existingToken) {
existingToken.count++;
} else {
result.push({currency: item.currency, token, count: 1, price: service.price});
}
});
});
});
} catch (e) {
error = "error";
}
return error ? [1, {error}] : [0, {result}]
Any way to make it "fool-proof" with some kind of "UNIQUE" safe guard?
Note: I'm beginner in JS.
I've used OpenAI's playground and it gave me the right function!
It suggested to "modify the existing code to use a Map data structure instead of an array to store the token count information. The Map will allow to keep track of each token, currency, and price combination as a key, and its count as the value"
const data = inputs.data;
const result = [];
let error = null;
try {
const tokenMap = new Map();
data.forEach(item => {
item.services.forEach(service => {
service.category.forEach(tokenObject => {
const token = tokenObject.token;
const key = `${token}-${service.price}-${item.currency}`;
if (tokenMap.has(key)) {
tokenMap.set(key, tokenMap.get(key) + 1);
} else {
tokenMap.set(key, 1);
}
});
});
});
tokenMap.forEach((count, key) => {
const [token, price, currency] = key.split('-');
result.push({currency, token, count, price: Number(price)});
});
} catch (e) {
error = "error";
}
return error ? [1, {error}] : [0, {result}]

moving a key value pair out of an array

I am trying to move everything in the Array Results outside and into the original object
this is the object
{
"Name": "John",
"Results": [
{
"Type": "DB",
"Immediate_Action": "No",
}
]
}
It should look like this
{
"Name": "John",
"Type": "DB",
"Immediate_Action": "No",
}
What I have so far is this
const mapOscarResults = ({ data }) => {
return data.map(entry => {
let mapped = {...entry};
entry.Results.forEach(key => {
let Type = mapped[key.Type]
if (mapped[key]) {
mapped[key].push(entry.Results[key]);
} else {
mapped[key] = [entry.Results[key]];
}
});
return mapped;
});
};
You can simply spread the Results array into an Object.assign() call.
const input = { "Name": "John", "Results": [{ "Type": "DB", "Immediate_Action": "No", }, { "Another": "value" }] };
const { Results, ...refactored } = input;
Object.assign(refactored, ...Results);
console.log(refactored)
This code works for your example:
const { Results: results, ...rest } = {
"Name": "John",
"Results": [
{
"Type": "DB",
"Immediate_Action": "No",
}
]
}
const res = {...rest, ...results.reduce((prev, curr) => ({
...prev,
...curr
}), {})}
console.log(res)
But I don't know what you expect when the Results array has more than one element.
In that condition, if this code does not fill your needs, ask me to change it.
however, it will join first Result with index 0, you can expand it
const data = {
"Name": "John",
"Results": [
{
"Type": "DB",
"Immediate_Action": "No",
}
]
}
const mapOscarResults = (data) => {
for (let i in Object.keys(data)){
if (Array.isArray(data[Object.keys(data)[i]])){
newKey = data[Object.keys(data)[i]][0]
data = {... data, ...newKey}
delete data[Object.keys(data)[i]]
}
}
return data
};
console.log(mapOscarResults(data))

React changing array label names on map output

I have a React component which is access JSON data for populate a tree component. The tree is showing nodes and ports. Here is a sample from the JSON:
"outputs": {
"graph": {
"nodes":[ {
"name":"nlabme3400",
"ports":[ {
"name": "GigabitEthernet 0/2", "id": "5bd350c7-d15b-4f8b-be70-18eda2bfe41a"
}
,
{
"name": "FastEthernet 0/19", "id": "5bd350c7-762d-4462-984b-e6f0a9edb6c7"
}
,
{
"name": "FastEthernet 0/21", "id": "5bd350c7-2927-43db-ae43-119b12636de6"
}
],
"id":"5bd350bf-8515-4dc2-9b12-16b221505593"
}
I have all of this information coming in to my component via the following axios get call:
axios.get('StepThreeFinalData.json').then(response => {
const nodess = response.data.outputs.graph.nodes.map(({id, name,
...children}) => ({value: id, label: name, children: children.ports}));
The output is working perfectly. However, the challenge is that I need to change the "name" and "id" tags in the children array to "label" and "value", respectively, because otherwise the label will not show up in the tree component. Not sure how to do this. Please help!
const ports = [ {
"name": "GigabitEthernet 0/2", "id": "5bd350c7-d15b-4f8b-be70-18eda2bfe41a"
}
,
{
"name": "FastEthernet 0/19", "id": "5bd350c7-762d-4462-984b-e6f0a9edb6c7"
}
,
{
"name": "FastEthernet 0/21", "id": "5bd350c7-2927-43db-ae43-119b12636de6"
}
]
const update_ports = (ports) => ports.map(({ id, name }) => {
return { label: name, value: id }
})
console.log(update_ports(ports)) // The new ports with the new keys and values.
You can use the map function and return new array of objects with new keys and values in each item in the array.
axios.get('StepThreeFinalData.json').then(response => {
const nodess = response.data.outputs.graph.nodes.map(({id, name,
...children}) => ({value: id, label: name, children: update_ports(children.ports)}));
Notice i've called to update_ports in your axios success.
const test = {
"outputs": {
"graph": {
"nodes": [{
"name":"nlabme3400",
"ports": [
{
"name": "GigabitEthernet 0/2", "id": "5bd350c7-d15b-4f8b-be70-18eda2bfe41a"
},
{
"name": "FastEthernet 0/19", "id": "5bd350c7-762d-4462-984b-e6f0a9edb6c7"
},
{
"name": "FastEthernet 0/21", "id": "5bd350c7-2927-43db-ae43-119b12636de6"
}
],
"id":"5bd350bf-8515-4dc2-9b12-16b221505593"
}]
}
}
};
const test2 = test.outputs.graph.nodes.map(({name, ports, id}) => ({
name,
id,
ports: ports.map(({name, id}) => ({
label: name,
value: id
}))
}));
console.log(test2);
Read more about map, filter, reduce, that will save your life
axios.get('StepThreeFinalData.json').then(response => {
const nodess = response.data.outputs.graph.nodes.map(({id, name,
...children}) => ({value: id, label: name, children: update_ports(children.ports)}));

Combine es6 function every and sum and return boolean

I have a JSON response
{
"nextAction": [{
"userList": [{
"id": 8,
"email": "testemail#gmail.com",
"name": "John Doe"
}],
"buttonLabel": "Finalize Now"
},
{
"userList": [{
"id": 10,
"email": "newemail#gmail.com",
"name": "Test User"
}],
"buttonLabel": "Start Now"
}
]
}
The userList array sometimes contain null object.
I am working on a condition which satisfies the below 3 conditions.
The nextAction array should be non-empty.
The userList array shouldn't contain the null element.
The currentUser should be present in the userList array.
const data = [{
"userList": [{
"id": 8,
"email": "testemail#gmail.com",
"name": "John Doe"
}],
"buttonLabel": "Finalize Now"
},
{
"userList": [{
"id": 10,
"email": "newemail#gmail.com",
"name": "Test User"
}],
"buttonLabel": "Start Now"
}]
function checkForMyNextActions(myNextActions, currentUser) {
const checkUsername = obj => obj.email === currentUser;
return (myNextActions.forEach((myAction, index) => {
(myAction.userList.length &&
myAction.userList.every(userList =>
userList !== null) &&
myAction.userList.some(checkUsername)
)
}))
}
var result = checkForMyNextActions(data, "testemail#gmail.com")
console.log(result)
The expected result is true whereas I get undefined.
You could do this via some & find:
var obj = {
"nextAction": [{
"userList": [{
"id": 8,
"email": "testemail#gmail.com",
"name": "John Doe"
}],
"buttonLabel": "Finalize Now"
}]
}
const getUser = (usr) => obj.nextAction.some(({
userList
}) =>
userList ? (userList.every(userList => userList !== null) &&
userList.find(y => y.email === usr)) : false)
console.log(getUser("testemail#gmail.com")) // true
console.log(getUser("test#gmail.com")) // false
The nice thing about some method is that it returns boolean if one element matches the condition which in our case is the inner find for the email.
You can go little further and make the function accept a field to match on as well like this:
var obj = { "nextAction": [{ "userList": [{ "id": 8, "email": "testemail#gmail.com", "name": "John Doe" }], "buttonLabel": "Finalize Now" }] }
const getUser = (field="email", usr) => obj.nextAction.some(({userList}) =>
userList ? userList.find(y => y[field] === usr): false)
console.log(getUser("email", "testemail#gmail.com")) // true
console.log(getUser("name", "John Doe")) // true
checkForMyNextActions returns undefined because forEach returns undefined. Use map to call a function on each element in an array and return a new array with the return values of the functions. Also the inner function passed to forEach does not return anything.
You can simply use Array.reduce() for this:
const data = [{ "userList": [{ "id": 8, "email": "testemail#gmail.com", "name": "John Doe" }], "buttonLabel": "Finalize Now" }];
function checkForMyNextActions(myNextActions, currentUser) {
const checkUsername = obj => obj.email === currentUser;
return myNextActions.reduce((a,curr)=>{
let bool = curr.userList.length && curr.userList.every(userList =>userList !==null) && curr.userList.some(checkUsername);
return bool && a;
},true) != 0;
}
var result = checkForMyNextActions(data, "testemail#gmail.com")
console.log(result)

how to map this array if i want to the Names of the groups listed in different "quesytion"

How can I get the names of different activity in an array by using map function in this type of response. So that in a new array, assume that activity[] i will get names of all the activities mention below.
if the array is
const response = [
{
"Groups" : {
"Roles" : {
"submission": {
"subject" : {
"name": "history",
}
}
}
}
}
];
I managed to do this using an IIFE but there may be cleaner ways
assuming there in one object in the array and no other path to other permission
const response = [
{
"Roles" : {
"Permission" : {
"PERMISSION1": {
"Activity" : {
"name": "Manage Clients",
}
},
"PERMISSION2": {
"Activity" : {
"name": "Manage Users",
}
}
}
}
}
];
let activities = (() => {
let res = []
for (let perm in response[0].Roles.Permission) {
for (let act in response[0].Roles.Permission[perm]) {
res.push(response[0].Roles.Permission[perm][act].name)
}
}
return res})()
console.log(activities)
At first, you should convert Permission object to array, cause object doesn't have method map.
Then you could use map function where you can collect all your permissions' names for every item in response
const response = [{
"Roles": {
"Permission": {
"PERMISSION1": {
"Activity": {
"name": "Manage Clients",
}
},
"PERMISSION2": {
"Activity": {
"name": "Manage Users",
}
}
}
}
}];
response.forEach((item) => {
item.Activities = Object.values(item.Roles.Permission).map((permission) => permission.Activity.name)
});
alert(JSON.stringify(response));
The only array you have is response. If each item in response has a Roles that has a Permission that has several keys with objects that have Activity with name then you can do the following:
var response = [
{
Roles: {
Permission: {
PERMISSION1: {
Activity: {
name: 'Manage Clients',
},
},
PERMISSION2: {
Activity: {
name: 'Manage Users',
},
},
},
},
},
];
console.log(
response.map(
(item) =>
Object.values(item.Roles.Permission)
.map(
(permission) => permission.Activity.name
)
)
);
I recommend using a flatMap, so use .reduce.
const response = [{
"Roles": {
"Permission": {
"PERMISSION1": {
"Activity": {
"name": "Manage Clients",
}
},
"PERMISSION2": {
"Activity": {
"name": "Manage Users",
}
}
}
}
}];
const activityNames = response.reduce(function (acc, res) {
const permissions = res.Roles.Permission;
const permissionKeys = Object.keys(permissions);
const names = permissionKeys.map(function(permissionKey) {
return permissions[permissionKey].Activity.name;
});
acc.push(...names);
return acc;
}, [])
console.log(activityNames); // ["Manage Clients", "Manage Users"]

Categories