How to overwrite data from a multi dimensional array in javascript? - javascript

I got a multidimensional array where each array inside is a combination of all the user info (put in by the user)
I want the user to be able to modify his information, such as his name or phone number, so that the next time the user logs in, his new info is displayed.
The userList is saved on JSON, the idea would be for the changes to be saved and loaded from there.
Example:
if my array has
userList= JSON.parse(localStorage.getItem('userListLS')
if(userList == null) {
userList =
[
['Isaac', 'Garth', 'IsaacG11#email.com', 'Mazda']
['Matthew', 'Miller', 'mmiller21#mail.com', 'Volvo']
]
}
and lets say Isaac is logged in, and he wishes to change his name to Gabriel and change email to IsaacG21#email.com, so that the new array would be:
userList= [
['Gabriel', 'Garth', 'IsaacG21#email.com', 'Mazda']
['Matthew', 'Miller', 'mmiller21#mail.com', 'Volvo']
]
how could this be accomplished?
Only JS and HTML please.

The easiest approach would be to modify the data directly using index selectors:
This approach mutates the initial array instead of returning a new reference, which can lead to unwanted side effects.
function modifyData(data, userId, fieldId, newData) {
if(data[userId] && data[userId][fieldId]) {
data[userId][fieldId] = newData;
}
return data;
}
// example
var userList= [
['Isaac', 'Garth', 'IsaacG11#email.com', 'Mazda'],
['Matthew', 'Miller', 'mmiller21#mail.com', 'Volvo']
];
const FIELD_NAME_ID = 0;
const USER_ID = 0;
var modified = modifyData(userList, USER_ID, FIELD_NAME_ID, 'Morty')
console.log('initial', userList);
console.log('modified', modified);
An immutable approach would be:
function modifyData(data, userId, fieldId, newData) {
if(data && data[userId] && data[userId][fieldId]) {
var _data = data.slice();
var _user = data[userId].slice();
_user[fieldId] = newData;
_data[userId] = _user;
return _data;
}
return data;
}
// example
var userList= [
['Isaac', 'Garth', 'IsaacG11#email.com', 'Mazda'],
['Matthew', 'Miller', 'mmiller21#mail.com', 'Volvo']
];
const FIELD_NAME_ID = 0;
const USER_ID = 0;
var modified = modifyData(userList, USER_ID, FIELD_NAME_ID, 'Morty');
console.log('initial', userList);
console.log('modified', modified);
But you should consider changing your structure to a dictionary of objects:
{
user1: { name: 'Isaac', lastName: 'Garth' /* ... */ }
// ...
}
or an array of objects (but then you have to find the right user in the array:
[
{ name: 'Isaac', lastName: 'Garth' /* ... */ }
// ...
]

A good usecase for a Map:
const users = new Map(
userList.map(
( [first,name,email,car]) => [first, { first,name,email,car }]
)
);
So to change a certains users email:
users.get("Isaac").email = "test # gmail.com";
A few more usecases:
//set a whole user:
users.set("Jack", {
first:" Jack",
name:"Daniels",
email:"me#example.com",
car:"VW"
});
//get an array of users again
userList = [...users.values()];

Related

Merging values from an array of strings into a nested object in javascript

I want to merge values from an array into a static nested object. The array containing the values is something like this,
['name=ABC XYZ', 'hobbies=[M,N,O,P]', 'profession=S', 'age=27']
and the object in which the values has to be merged is,
const person = {
details_1: {
name: null,
hobbies: null,
profession: null
},
details_2: {
age: null
}
};
I want my output object to look like below,
const updated_person = {
details_1: {
name: 'ABC XYZ',
hobbies: [M,N,O,P],
profession: 'S'
},
details_2: {
age: 27
}
};
Thanks a lot for your help!
I made another solution with a different approach.
Here I used an interface weher I described the desired data structure.
In the second part the string array is tranformed into key and value pairs. Thereform are filtered the keys of interface and added into an empty object literal.
const data = ["name=ABC XYZ", "hobbies=[M,N,O,P]", "profession=S", "age=27"];
const dataInterface = {
details_1: { name: null, hobbies: null, profession: null },
details_2: { age: null },
};
function orederData(arr) {
const record = arr.map((item) => {
let [key, value] = item.split("=");
if (value[0] === "[" && value[value.length - 1] === "]") {
value = value.slice(1, value.length - 1).split(",");
}
return { key, value };
});
const dataBlock = {};
Object.keys(dataInterface).map((detail) => {
dataBlock[detail] = {};
Object.keys(dataInterface[detail]).forEach((dataKey) => {
dataBlock[detail][dataKey] = record.filter((record) => {
return record.key === dataKey;
})[0].value;
});
});
return dataBlock;
}
const orderedData = orederData(data);
console.log(orderedData);
You can simply achieve this by iterating the input array.
const arr = ['name=ABC XYZ', 'hobbies=[M,N,O,P]', 'profession=S', 'age=27'];
const person = {
details_1: {},
details_2: {}
};
arr.forEach(item => {
(item.split('=')[0] !== 'age') ? person.details_1[item.split('=')[0]] = item.split('=')[1] : person.details_2[item.split('=')[0]] = item.split('=')[1]
});
console.log(person);
There is no way to cleanly merge an unstructured array into a structured object such that the array values end up in the appropriately keyed person properties.
javascript does provide the assign() function that merges objects but for YOUR requirements your source data needs to be an object similarly structured and not an array.
so this:
['name=ABC XYZ', 'hobbies=[M,N,O,P]', 'profession=S', 'age=27']
would need to become this:
const source= [{details_1: {"name":"ABC XYZ", "hobbies":"[M,N,O,P]", "profession":"S"}, details_2: {"age":"27"}}]
such that a call to Object.assign():
const new_person = Object.assign(person, source[0]);
fills this
const person = {
details_1: {
name: null,
hobbies: null,
profession: null
},
details_2: {
age: null
}
};
properly, though you may need to clone or instantiate and empty person first.
or, if person is an Object you could have a fill() method that knows what to do with the array data.

Merged array search functionality is not working

I'm having two data arrays which are coming from API and sample arrays would be like this
Array 1
[
{userId: 1
description: "Student"
imagePath: "test.png"
status: 1
}]
Array 2
[
{id: 85
accountName: "Rahul"
accountNumber: "11145678"
}
]
In my reactnative app view there's search bar and user should be able to search from these two arrays. So I merged these two arrays into one using
this.searchArray =this.filterArray[0].concat(this.filterArray[1])
So, my searchArray is a single array with Array1 and Array2 data. sample below
[
{userId: 1
description: "Student"
imagePath: "test.png"
status: 1
},
{id: 85
accountName: "Rahul"
accountNumber: "11145678"
}]
My search function is below (I need to search from account number or description)
//Search Filter
searchFilter =searchText=>{
const searchTextData = searchText.toUpperCase();
const userSearch = this.searchArray.filter(item => {
const itemData = `${item.description && item.description.toUpperCase()} ${item. accountName && item.accountName.toUpperCase()}`;
return itemData.indexOf(searchTextData) > -1;
});
}
The search functionality is not working with accountName. It's not getting any results. But if I remove ${item. accountName && item.accountName.toUpperCase()} , then it's working showing data with description. But I need to filter from both
In your array one object can have description or accountNumber so do a check if that exists include it in the itemData variable.
Try doing this
searchFilter =searchText=>{
const searchTextData = searchText.toUpperCase();
const userSearch = this.searchArray.filter(item => {
const itemData = `${item.hasOwnProperty('description'))?item.description.toUpperCase():''} ${item.hasOwnProperty('accountNumber')?item.accountNumber:''}`;
return itemData.indexOf(searchTextData) > -1;
});
}
First merge the two objects into one:
Object.keys(arr2[0]).forEach(key => {
arr1[0][key] = arr2[0][key]
})
Then create the search function:
function searchObject(obj, value){
return Object.keys(obj).some(key => {
return obj[key] === value
})
}
let arr1=[{userId:1,description:"Student",imagePath:"test.png",status:1}],arr2=[{id:85,accountName:"Rahul",accountNumber:"11145678"}];
Object.keys(arr2[0]).forEach(key => {
arr1[0][key] = arr2[0][key]
})
function searchObject(obj, prop, value){
return obj[prop] === value
}
console.log(searchObject(arr1[0], "accountName", "asdf"))
console.log(searchObject(arr1[0], "accountName", "Rahul"))

Load data in the object?

I am not sure if i'm doing the right approach, I am doing like class style. Is there a way to load data in the object using loadProducts(data) so then I can call orderLines.getItemsType()
const orderProducts = {
loadProducts: function(data) {
//Load data into orderProducts object?
},
getItemsType: function(type) {
// return data
}
};
Usage:
const items = orderProducts.getItemsType(['abc', 'ddd']);
Note: It is for node.js, not for the browser.
First you want to save the products into a property. We will load the property with some dummy data.
We can then filter the data using filter and test if the item is in the products array like this:
const orderProducts = {
// The list of products
products: [],
// The products to load
loadProducts: function(...data) {
this.products.push(...data)
},
// Get items passed in
getItemsType: function(...type) {
return this.products.filter(p => type.includes(p))
}
}
orderProducts.loadProducts('abc', '123', '111', 'ddd')
const items = orderProducts.getItemsType('abc', 'ddd')
console.log(items)
I guess next approach can help you to make it class approach and solving your question:
class OrderProducts {
constructor(data) {
this.data = data;
this.getItemsType = this.getItemsType.bind(this);
}
getItemsType(type) {
// return the data filtering by type
return this.data;
}
}
// usage
const orderProduct = new OrderProduct(data);
const items = orderProduct.getItemsType(['abc', 'ddd']);

Normalizing my nested JSON with normalizr

I'm having the following JSON from my service:
[
{
"name":"Voter1",
"id":1,
"votingCard":{
"verificationCodes":[
"3I08jA",
"3x0eyE",
"2_i69I"
],
"votingCode":"7zCOelDnjfBm7TtFydc4QodgonG",
"finalizationCode":"jyYu",
"confirmationCode":"4ACfcpBVH45iAXqg7hJ0tbEe_tV"
}
},
.....
{
"id":5,
"name":"Voter5",
"votingCard":{
"verificationCodes":[
"2c9I9a",
"3bEeEa",
"1gPKx2"
],
"confirmationCode":"4Z7wNG35VR2UMO6-W-0aZVEhbLM",
"votingCode":"6YQ2x-c8LXJZF05gh3zTajU79ct",
"finalizationCode":"S0CY"
}
}
]
And would like to get it normalized, so a list of votingCards and a list of voters with a "votingCard" property referencing the votingCard by id.
import { normalize, schema } from 'normalizr';
const votingCard = new schema.Entity('votingCard');
const voter = new schema.Entity('voter', {
votingCard: votingCard,
});
const votersSchema = new schema.Array(voter);
const mutations = {
SOCKET_SYNCVOTERS: (state, data) => {
var input = JSON.parse(data);
const normalizedData = normalize(input, votersSchema);
console.log(normalizedData);
},
};
However, I'm not getting what I want:
Why is there an "undefined"?
I think you need to specify an ‘idAttribute’ in the options for the votingCard entity - the problem is that normalizr can’t find an ‘id’ field in those objects so they are all being picked up as id undefined and overwriting each other in entities. See: https://github.com/paularmstrong/normalizr/blob/master/docs/api.md#schema

Select all from array where key: name is equal something

I have got array of var players = [] that holds info like userID, userScore etc.. usually I would select specific player by doing something like players[i] where i is a number position in array. But for one bit of my application I do not know this number, but I do know userID And I'm trying to figure out how to update userScore in players array where userID is equal to something, lets say abc_123
for(var i = 0; i < players.length; i++){
if(players[i].userId === 'someId'){
//doSomething(player[i]);
players[i].userScore = 'abc_123';
}
}
You could use the Array.find method:
var players = [ { userId: 123 } ];
var user = players.find(function(item) {
return item.userId === 123;
});
if (user != null) {
// user is the first element in the players array that
// satisfied the desired condition (a.k.a user.userId === 123)
}
Assuming the array items are objects, you can use the filter function:
var player = players.filter(function(p)
{
return p.userID == "something";
}).forEach(function(p) {
p.userScore = "something";
});
You could use the filter function.
var findId = 'jkl';
var theGoose = players.filter(function(user){ return user.userId === findId; }).pop();
var players = [
{
userId: 'abc',
userInfo: 'duck'
},
{
userId: 'def',
userInfo: 'duck'
},
{
userId: 'ghi',
userInfo: 'duck'
},
{
userId: 'jkl',
userInfo: 'goose!'
},
{
userId: 'mno',
userInfo: 'duck'
}];
var findId = 'jkl';
var theGoose = players.filter(function(user){ return user.userId === findId; }).pop();
$('#debug').text( theGoose.userInfo );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="debug"></div>
You might want to use a Dictionary rather than an array. The key can naturally be the player ID. The rest of the information can be put in some object type. Then you can easily access the Dictionary by key.
Try with grep:
var players = [
{score: 10,userId: 1},
{score: 20,userId: 2},
{score: 30,userId: 3}
];
function findByUsrId(id){
return $.grep(players, function(item){
return item.userId == id;
});
};
console.log(findByUsrId(2));
Jsfiddle here: http://jsfiddle.net/pfbwq98k/

Categories

Resources