Convert array to an array object with some modifications - javascript

i'm pretty beginner in the JavaScript and I really need help to convert an array to an array object. There are many examples here in stackOverflow, but I need some modidfication during this process, which is why I couldn't do anything
For example I have:
data = [{id: 21, name: "jack"} , {id: 185, name: "yas"}]
and I need to convert it with something like that (id key change to student_id, and present = true, should be added), and the length of this array is dynamic and will change over time.
[
{
"student_id" : 21,
"present" = true
},
{
"student_id" : 185,
"present" = true
}
]
I need to add these array object to:
const data: any = {
here....
};
your help will be much appreciated.

Assuming your data actually looks more like this
data = [{id: 21, name: "jack"}, {id: 185, name: "yas"}]
This is a simple matter of mapping the array to a new format with the properties you want
const data = [{id: 21, name: "jack"}, {id: 185, name: "yas"}]
const newData = data.map(({ id }) => ({
student_id: id,
present: true
}))
console.log(newData)

Related

How to use JavaScript spread... syntax to change the one field of the object, that belongs to the array and is accessed by name-value pair?

Here is the code (it fails to compile at the sentence that builds the state2, i.e. at the second spread):
let line_id = 6;
let state = {
invoice: {
id: 1015,
description: 'web order',
},
lines: [
{id: 5, description: 'phone', color: 'black'},
{id: 6, description: 'tablet', color: 'blue'},
{id: 7, description: 'computer', color: 'gray'},
]
};
//this alert and this access pattern works, so, I would like to use
//.find... to access element in spread... structure as well
//alert(state['lines'].find(line=>line['id']==line_id)['description']);
let state2 = {
...state,
['lines']: { ...state['lines'],
find(line=>line['id']==line_id): { ...state['lines'].find(line=>line['id']==line_id),
['description']: 'TV',
},
},
};
alert(state2['lines'].find(line=>line['id']==line_id)['description']);
I have state structure, I access lines array, I access the specific line by name-value pair id=6 and I would like to change the value of the field description. This effort is the continuation of https://stackoverflow.com/a/64116308/1375882 in which I am trying to create the general procedure, that use the spread... syntax and the access-by-name strategy for updating the complex object/array tree. In fact - this complex tree is the state of the Redux reducer and that update happend in the action that process the valueSetter function of the AgGrid. But - this is generally the interesting exercise by itself to better understand spread... and JavaScript and JSON structure in JavaScript.
So - the only question is: how to write line
find(line=>line['id']==line_id): { ...state['lines'].find(line=>line['id']==line_id),
so that the code compiles? How can I access the certain element of the array by name-value pair in this setting:
Note, that I am trying to build general code:
find(line=>line[keyFieldName]==keyFieldValue): { ...state['lines'].find(line=>line[keyFieldName]==keyFieldValue),
that uses arbitrary field names and field values - so that such handler can update the any field of the any record of arbitrary 2D AgGrid in React/Redux setting.
The desired result of my code: 1) it should compile; 2) the second alert should return 'TV'.
If I understood correctly what you want to achieve, this should work:
let line_id = 6;
let state = {
invoice: {
id: 1015,
description: 'web order',
},
lines: [{
id: 5,
description: 'phone',
color: 'black'
},
{
id: 6,
description: 'tablet',
color: 'blue'
},
{
id: 7,
description: 'computer',
color: 'gray'
},
]
};
const stateKeyId = 'lines';
const itemKeyId = 'id';
const itemAttr = 'description'
let state2 = {
...state,
[stateKeyId]: state[stateKeyId].map(item => {
if (item[itemKeyId] == line_id) {
return ({
...item,
[itemAttr]: 'TV'
});
}
return item
})
}
console.log(state2);
find(line=>line['id']==line_id) should become [find(line=>line['id']==line_id)], since just like the string it must be between square brackets for js to work properly.
Also, if you are using find from lodash, it will return the object, therefore if you need to use the id as key you can do something like:
[get(find(line => line['id'] === line_id]), 'id')]: whatever
a few observations though:
always please always use === over == in js
avoid snake_case, use camelCase with js, since it's standard
your code is not actually handling missing items correclty, if you need to do so split it in multiple lines since it would be more comprehensible
You can use the map method from arrays to return different elements based on the original one.
Here's how you could use it:
line_id = 6;
state = {
invoice: {
id: 1015,
description: 'web order',
},
lines: [
{id: 5, description: 'phone', color: 'black'},
{id: 6, description: 'tablet', color: 'blue'},
{id: 7, description: 'computer', color: 'gray'},
]
};
state2 = {
...state,
lines: state.lines.map(line => {
if (line.id === line_id)
return { ...line, description: 'YT' }
return { ...line }
})
};
alert(state2['lines'].find(line=>line['id']==line_id)['description']);

Javascript array difference

I have two arrays like so
data = [{id: 1, name: apple},
{id: 2, name: mango},
{id: 3, name: grapes},
{id: 4, name: banana}]
data2 =[{id: 1, name: apple},
{id: 3, name grapes}]
My Expected result would be:
[{ id: 2, name: mango},
{id:4, name: banana}]
My code is
let finalData =[];
data.forEach(result => {
data2.find(datum => {
if(datum['id'] === result['id]{
finalData.push(result);
}
})
})
I am getting wrong result. What is the simplest code or library that I can use?
Your sample data doesn't make sense, but assuming you mean that all data items that have matching IDs also have matching names and also assuming you want a set of all items where the IDs are the same in the two sets of data, you could use a Set to keep track of which IDs are present in one array then filter the second array by those that have their IDs in the set:
const idsInFirst = new Set(data.map(d => d.id));
const intersection = data2.filter(d => idsInFirst.has(d.id));
The reason why an intermediate Set structure is used is because it allows O(1) lookups after a one-time scan, which is more efficient than repeatedly scanning the first array over and over.
If you meant to say you wanted a difference between data sets (items excluded from data that are in data2), you'd want to negate/inverse things a bit:
const idsToExclude = new Set(data2.map(d => d.id));
const difference = data.filter(d => !idsToExclude.has(d.id));
Edit
After your clarifying edit, it's that second block of code that you'll want.
I would say a good way to do that is filtering your longest array using a function that will validate if the object id is present in both arrays. Check this example:
const data = [
{id: 1, name: 'apple'},
{id: 2, name: 'mango'},
{id: 3, name: 'grapes'},
{id: 4, name: 'banana'}
]
const data2 =[
{id: 1, name: 'apple' },
{id: 3, name: 'grapes' }
]
const longest = data.length > data2.length ? data : data2;
const shortest = data.length <= data2.length ? data : data2;
const finalData = longest.filter( obj => !shortest.find( o => o.id === obj.id ) )
console.log(finalData)
Good luck!

map an array from an array of objects key/value

I need to take an array objects that and map it so that the new array is just a simple array if each object's id.
So for example:
[
{id: 49, name: "Rest update test"},
{id: 12, name: "Rest test"}
]
would become:
[49, 12]
i have tried this so far:
myObject.map(object => object.id);
so my actual function that is not working is the following, when I view the console.log, it is showing the original object:
onSubmit() {
this.userForm.value.accountsToAdd.map(object => object.id);
console.log(this.userForm.value.accountsToAdd);
}
Assuming the given code does not work, then you need to assign the result of mapping.
Array#map does not mutate the original array but return a new one.
var array = [{ id: 49, name: "Rest update test" }, { id: 12, name: "Rest test" }],
ids = array.map(object => object.id);
console.log(ids);

How to merge two arrays into one array in angularjs?

This is my code
$scope.studentDetails=[];
$scope.studentDetails=[0][id:101,name:one]
[1][id:102,name:two]
[2][id:103,name:three]
$scope.studentMarks=[];
$scope.studentMarks=[0][id:101,marks:78]
[1][id:102,marks:89]
i have two arrays,first array contains 2 properties like id and name, second array contains two properties like id and marks,i want to concatinate these two arrays into one array.i want to get output like
$scope.studentDetails=[0][id:101,name:one,marks:78]
[1][id:102,name:two,marks:89]
[2][id:103,name:three,marks:null]
Lodash zip() should do that provided your JavaScript is valid in the first place.
$scope.studentDetails = _.zip($scope.studentDetails, $scope.studentMarks);
I got the answer
var newArray = [];
_.each($scope.studentDetails,function(obj))
{
var data=_.findWhere($scope.studentMarks,{"id":obj.id});
if(!_.isUndefined(data))
{
newArray.push({id:obj.id,name:obj.name,marks:data.marks});
}
else
{
newArray.push({id:obj.id,name:obj.name,marks:"null"});
}
}
Hey you can use the push like
$scope.studentDetails.push({'id':'101','name':'one','marks':'78'});
$scope.studentDetails.push({'id':'102','name':'two','marks':'78'});
$scope.studentDetails.push({'id':'103','name':'three','marks':'78'});
using loop you can append like bellow
for(i = 0; i < studentResult.length; i++){
$scope.studentDetails.push(studentResult[i]);
}
For object array _.zip merged two array into single array where each array element also an array.
You can use .map and .extend to create merged object array with _.zip like
var studentDetails = [{ id: 101, name: 'one' }, { id: 102, name: 'two' }, { id: 103, name: 'three' }];
var studentMarks = [{ id: 101, marks: 78 }, { id: 102, marks: 89 }];
var mergedArray = _.zip(studentDetails, studentMarks); //where each element also an array like [ [{ id: 101, name: 'one' }, { id: 101, marks: 78 }] ]
var studentDetails = _.map(mergedArray, function (item) { return _.extend(item[0], item[1]); }); //[{ id: 101, marks: 78, name: 'one' }, ..]

I have two arrays, how do I find matchings elements and perform some action? (lodash)

var array1 = [{Age: 24, Name: "Test", StudentID: 101, Checked: false}, {Age:25, Name: "Test", StudentID: 102, Checked: false}];
var array2 = [{ID: 101}];
If any element in array1 has a property of StudentID that is equal to an ID property present in array2 I'd like to set the Checked property in array1 to true.
Any tips? I'd like to do this without writing nested _.each statements.
This is my first take; however, I believe _.some performs an interation anyway.
_.each($scope.array1, function(element1) {
if(_.some($scope.array2, { ID: element1.ID })) {
element1.Checked = true;
}
});
You''ll have to use two loops, since you have two arrays of random length. But you don't have to nest them. Create a map from the array of IDs and then check the index.
var availableIDs = array2.map(function ( item ) { return item.ID; });
array1.forEach(function ( item ) {
if (availableIDs.indexOf(item.StudentID) !== -1) item.Checked = true;
});
Using lodash, use a sequence in which you create a map of items in array1, using _.indexBy(). Create an array of ids from array2 using _.pluck(), and use them with _.at() to get the selected items. Iterate the returned objects using _.forEach() to set the Checked property to true, and .commit() to apply the changes:
function checkById(items, selected) {
_(items) // start chained sequence
.indexBy('StudentID') // create a map of student objects by ids
.at(_.pluck(selected, 'ID')) // create an array of IDs from the objects in the selected array
.forEach(function(item) { // change the items Checked to true
item.Checked = true;
})
.commit(); // executes the chained sequence
}
var array1 = [{
Age: 24,
Name: "Test1",
StudentID: 101,
Checked: false
}, {
Age: 25,
Name: "Test2",
StudentID: 102,
Checked: false
}, {
Age: 22,
Name: "Test3",
StudentID: 103,
Checked: false
}, {
Age: 28,
Name: "Test4",
StudentID: 104,
Checked: false
}];
var array2 = [{
ID: 101
}, {
ID: 104
}];
checkById(array1, array2);
console.table(array1);
document.getElementById('demo').innerText = JSON.stringify(array1, null, ' ');
<script src="https://cdn.jsdelivr.net/lodash/3.10.1/lodash.min.js"></script>
<pre id="demo"></pre>
using a simple mapping function you can compose an easy search through all objects
var array1 = [{Age: 24, Name: "Test", StudentID: 101, Checked: false}, {Age:25, Name: "Test", StudentID: 102, Checked: false}];
var array2 = [{ID: 101}];
function search(studentList,searchQuery) {
var results = [];
studentList.forEach(function(student,sIndex) {
searchQuery.forEach(function(search,qIndex) {
if(search.ID == student.StudentID) {
results.push(student);
}
});
})
return results;
}
search(array1,array2);
what the forEach function does is iterate over each element, passing along the object of the index it's iterating, and the index that object is at.
By having a double nested map it's easy to iterate over the objects and then compare them according to the rules you define.
Then by using a scoped variable you can push matching values into that array, giving you a nice, neat clean result to return.
Now please mind, this is not the most efficient way to handle this. You could do a test which arary is longest and have that one iterate the least time.
So if there are more students than search parameters iterate the students once. If there are more search parameters than students, iterate the search paramateters once.
also you could chooose to 'prefilter" the arrays by sorting them on the index you wish to sort on, skip the ones you don't need by simple min/max exclusion and such.
But you'd be better off using a database query for searching with large quantities of data.
But if you only have a dataset of about a 1000 or so this will suffice.
Try this snippet:
_.each(array1, function (el) {
el.Checked = !!(JSON.stringify(array2).indexOf(el.StudentID) + 1) || el.Checked;
});
Or, you can do without lo-dash.js(with pure JavaScript)
var array1 = [{Age: 24, Name: "Test", StudentID: 101, Checked: false}, {Age:25, Name: "Test", StudentID: 102, Checked: false}];
var array2 = [{ID: 101}];
var students = array1.filter(function(data){
var isTrue = !!(JSON.stringify(array2).indexOf(data.StudentID)+1);
data.Checked = isTrue || data.Checked;
return isTrue;
})
console.log(students)

Categories