Push items in an array in Javascript? - javascript

I'm working on school-app. person enter students marks from frontend and I've to store it in my backend. I know my data-structure is quite bad. but this is only way I can comfortly use and fit it in my front end application/website.
codeSandbox link
Full Code:
//This data is already set need to push information in this array.
let student = [{
"detail": {
"name": "Mark",
"surname":"widen"
},
}];
//formatting the query in json.
const keys = Object.keys(query)[0].split(",")
const values = Object.values(query)[0].split(",")
const newObj = {}
for (let i = 0; i < keys.length; i++) {
newObj[keys[i]] = values[i]
}
// I've to push it along with "academic-year". so,
for (let a = 0; a < newObj.length; a++) {
const year = a + "st-Year"
console.log(year) // Expected Output: 1st-Year and 2nd-Year
}
// How to run this both for-loop synchronously way ?? AND
//pushing with "ObtainedMarks" and "year" (Error over here)
student.push({
ObtainedMarks: {
year : [
{ physics: newObj }
],
year : [
{ physics: newObj }
]
}
})
console.log(student) //Here's I want expected Output
Expected Output:
let student = [{
"detail": {
"name": "Mark",
"surname":"widen"
},
ObtainedMarks: {
"1st-Year": [
{ physics: { "marks": "500" } } //Physics subject is default.
],
"2nd-Year": [
{ physics: { "mark": "200" } } //Physics subject is default.
]
}
}];
I want to push returned data in student array. with 1st-Year
and 2nd-Year's for-loop.

You can do the conversion in your for-loop
let student = [{
"detail": {
"name": "Mark",
"surname": "widen"
},
}];
let query = {
"marks,mark": "500,200"
}
const keys = Object.keys(query)[0].split(",");
const values = Object.values(query)[0].split(",");
const marks = {}
for (let i = 0; i < keys.length; i++) {
marks[i === 0 ? `${i+1}st-year` : `${i+1}nd-year`] = [{
physics: {
[keys[i]]: values[i]
}
}];
}
student.push({
obtainedMarks: marks
});
console.log(student);
Alternative way: map through the keys and create an object from entries after manipulating the data.
let student = [{
"detail": {
"name": "Mark",
"surname": "widen"
},
}];
let query = {
"marks,mark": "500,200"
}
const keys = Object.keys(query)[0].split(",");
const values = Object.values(query)[0].split(",");
const marks = Object.fromEntries(keys.map((k, i) => {
return [
i === 0 ? `${i+1}st-year`: `${i+1}nd-year`,
[{ physics: { [k]: values[i] }}]
];
}));
student.push({
obtainedMarks: marks
});
console.log(student);

Related

JavaScript - How to change object keys in an array of object?

I have an array of object :
let data = [
{ "date" : "17/03/2022", "count" : 2, "james#email.net" : 2 },
{
"date" : "17/05/2022",
"count" : 2,
"admin#email.com" : 1,
"secretary#email.uk" : 1
},
{ "date" : "17/07/2022", "count" : 7, "staff#email.us" : 7 },
];
I would like to remove "#" in the object key instead of the email address.
This is the expected output :
// Expected output:
data = [
{ "date" : "17/03/2022", "count" : 2, "james" : 2 },
{
"date" : "17/05/2022",
"count" : 2,
"admin" : 1,
"secretary" : 1
},
{ "date" : "17/07/2022", "count" : 7, "staff" : 7 },
];
Notes:
james is from james#email.net (1st element)
admin and secretary are from admin#email.com and secretary#email.uk, respectively (2nd element)
staff is from staff#email.us (3rd element)
and so on.
email as object keys are dynamic, meaning it can be "johndoe#email.co.uk", "mary#email.net", etc.
I have tried, but yet not successful :
for (let i = 0; i < data.length; i++) {
let keys = Object.keys(data[i]);
console.log(`key-${i+1} :`, keys); // [ 'date', 'count', 'admin#email.com', 'secretary#email.uk' ]
let emails = keys.filter(index => index.includes("#"));
console.log(`email-${i+1} :`, emails); // [ 'admin#email.com', 'secretary#email.uk' ]
let nameList = [];
for (let i = 0; i < emails.length; i++) {
let name = emails[i].split("#")[0];
nameList.push(name);
}
console.log(`name-${i+1} :`, nameList); // [ 'admin', 'secretary' ]
}
Thanks in advance.
You could create a function which splits the keys of the object keys at # and creates a new object using Object.fromEntries().
Here's a snippet:
const data = [{date:"17/03/2022",count:2,"james#email.net":2},{date:"17/05/2022",count:2,"admin#email.com":1,"secretary#email.uk":1},{date:"17/07/2022",count:7,"staff#email.us":7}];
const converter = o => Object.fromEntries(
Object.entries(o).map(([k, v]) => [k.split("#")[0], v])
)
console.log(
data.map(converter)
)
If Object.fromEntries() is not supported, you could use a simple loop through the array and then each object to create new objects like this:
const output = []
for (const o of data) {
const updated = {}
for (const key in o) {
updated[key.split("#")[0]] = o[key]
}
output.push(updated)
}
Try this as short as simple:
let data = [{
"date": "17/03/2022",
"count": 2,
"james#email.net": 2
},
{
"date": "17/05/2022",
"count": 2,
"admin#email.com": 1,
"secretary#email.uk": 1
},
{
"date": "17/07/2022",
"count": 7,
"staff#email.us": 7
},
];
const refinedData = JSON.parse(JSON.stringify(data));
refinedData.map((el, i) => {
Object.keys(el).map(e => {
if(e.includes('#')){
refinedData[i][e.slice(0, e.indexOf('#'))] = refinedData[i][e];
delete refinedData[i][e];
}
})
});
console.log(data, refinedData);
Try this improvement to prevent shallow copy and let me know your thoughts.
Can you try using this?
for (let i = 0; i < data.length; i++) {
let element = data[i];
let keys = Object.keys(element);
let emails = keys.filter(index => index.includes("#"));
for (let j = 0; j < emails.length; j++) {
let name = emails[j].split("#")[0];
let value = element[emails[j]];
Object.defineProperty(element, name, { value });
delete element[emails[j]];
}
}
console.log(data);

Get parent object after looping through nested array

I have a nested array I loop through every element in the array and read the value of key title then I check if the value includes a certain string if it includes the search string that value will be pushed to another array then I sort the new array by occurrence of the search string so that the index position of every element in the new array depends how similar the array element string is with the search string and also the array elements will be sorted by ascending letter order. Now this whole procedure works fine. What I want is once I get the sorted new array I want to loop though it then get the object containing the new arrays element as a title. How can I achieve this. Read the comments in my code to better understand my question. Thanks in advance.
note: When retrieving the object it should keep the index position of the newly created array.
const allArr = [
[{
"id": "1",
"title": "blaha"
}, {
"id": "2",
"title": "blahe"
}, {
"id": "3",
"title": "dhs"
}],
[{
"id": "4",
"title": "blahc"
}, {
"id": "5",
"title": "shg"
}]
]
const searchTerm = 'blah'
let existsArr = []
let tempArr = []
for (var i = 0; i < allArr.length; i++) {
const allAds = allArr[i]
for (var j = 0; j < allAds.length; j++) {
if (allAds[j].title.toLowerCase().includes(searchTerm.toLowerCase())) {
existsArr.push(allAds[j].title)
}
}
}
tempArr = existsArr.filter(a => a.toLowerCase().includes(searchTerm))
const startsWith = (string, value) => string.substring(0, value.length).toLowerCase() === value
const sortByOccurance = JSON.stringify(tempArr.sort((a, b) => {
const aStartsWith = startsWith(a, searchTerm)
const bStartsWith = startsWith(b, searchTerm)
if (aStartsWith && !bStartsWith) {
return -1
} else if (!aStartsWith && bStartsWith) {
return 1;
}
return b > a ? -1 : 1
}))
console.log(sortByOccurance)
//now I want to get the object of every title found in sortByOccurance from allArr
//expected output:
//[{"id": "1", "title": "blaha"}, {"id": "4", "title": "blahc"}, {"id": "2", "title": "blahe"}]
Array.flat flattens the array a level (or more). That makes it easier to find an item.title === term. So now we can loop over array and build our result array.
Update: not using Array.flat to allow for duplicate names with different id. Instead, we search for the first match (a "deep" search) and then delete it so next time will find next item.
const allArr = [
[{
"id": "1",
"title": "blaha"
}, {
"id": "2",
"title": "blahe"
}, {
"id": "3",
"title": "dhs"
}],
[{
"id": "4",
"title": "blahc"
}, {
"id": "5",
"title": "shg"
}],
[{
"id": "6",
"title": "blaha"
}]
]
const searchTerm = 'blah'
let existsArr = []
let tempArr = []
for (var i = 0; i < allArr.length; i++) {
const allAds = allArr[i]
for (var j = 0; j < allAds.length; j++) {
if (allAds[j].title.toLowerCase().includes(searchTerm.toLowerCase())) {
existsArr.push(allAds[j].title)
}
}
}
tempArr = existsArr.filter(a => a.toLowerCase().includes(searchTerm))
const startsWith = (string, value) => string.substring(0, value.length).toLowerCase() === value
const sortByOccurance = JSON.stringify(tempArr.sort((a, b) => {
const aStartsWith = startsWith(a, searchTerm)
const bStartsWith = startsWith(b, searchTerm)
if (aStartsWith && !bStartsWith) {
return -1
} else if (!aStartsWith && bStartsWith) {
return 1;
}
return b > a ? -1 : 1
}))
function find_deep(arr, term) {
for (var i = 0; i < arr.length; i++) {
var value = arr[i]
if (Array.isArray(value)) {
var res = find_deep(value, term)
if (res) {
return res;
}
}
if (value.title === term) {
return value;
}
}
return null;
}
console.log(sortByOccurance)
var result = [];
JSON.parse(sortByOccurance).forEach(function(term) {
var found = find_deep(allArr, term)
if (found) {
result.push({ ...found
})
delete found.title; // <--- changes original allArr.
}
})
console.log(result)
.as-console-wrapper {
max-height: 100% !important
}

How can I merge object values if they have the same key?

I have an Array full of transactions and I want to divide it by day. It will be an array of date that is and array of transations. It may be a little messy but I want to return this structure.
What I tried to do returns me the structure I want, but I don't know how to merge duplicated key values.
This is the array
const transactions = [
{
name: "Salário",
receiveDate: "2020-05-12T00:00:00.000Z",
value: "1000",
},
{
name: "Pagamento ",
receiveDate: "2020-05-12T00:00:00.000Z",
value: "2350",
},
{
name: "Passagem no VEM",
paidDate: "2020-05-02T00:00:00.000Z",
value: "130",
},
{
name: "Almoço",
paidDate: "2020-05-08T00:00:00.000Z",
value: "50",
},
];
This is what I already tried by now
const days = [];
const finalArray = [];
for (let i = 0; i < transactions.length; i++) {
transactions[i].day = transactions[i].receiveDate || transactions[i].paidDate;
days.push(transactions[i].day);
}
const datesToMatch = [...new Set(days)].map((date) => {
return { [date]: null };
});
transactions.map((transaction) => {
datesToMatch.map((dayObject) => {
const day = Object.keys(dayObject).toString();
if (day === transaction.day) {
finalArray.push({ [day]: [transaction] });
}
});
});
The output
[ { '2020-05-12T00:00:00.000Z': [ [Object] ] },
{ '2020-05-12T00:00:00.000Z': [ [Object] ] },
{ '2020-05-02T00:00:00.000Z': [ [Object] ] },
{ '2020-05-08T00:00:00.000Z': [ [Object] ] } ]
Expected output
[ { '2020-05-12T00:00:00.000Z': [ [Object, Object] ] },
{ '2020-05-02T00:00:00.000Z': [ [Object] ] },
{ '2020-05-08T00:00:00.000Z': [ [Object] ] } ]
Thanks!
Explanation:
dates : extract dates from both fields
uniqueDates : build a Set and convert it into an array so it only has uniqueDates
dateToTransactions : map every unique date to an object with one key (itself) and filter every transaction that is equal to it.
const transactions = [{
name: "Salário",
receiveDate: "2020-05-12T00:00:00.000Z",
value: "1000",
},
{
name: "Pagamento ",
receiveDate: "2020-05-12T00:00:00.000Z",
value: "2350",
},
{
name: "Passagem no VEM",
paidDate: "2020-05-02T00:00:00.000Z",
value: "130",
},
{
name: "Almoço",
paidDate: "2020-05-08T00:00:00.000Z",
value: "50",
},
];
const dates = transactions.map(x => {
const received = x.receiveDate || [];
const paid = x.paidDate || [];
return received + paid;
});
const uniqueDates = [...new Set(dates)];
const dateToTransactions =
uniqueDates.map(
date => {
sameDate = transactions.filter(x => x.receiveDate === date || x.paidDate == date);
return {[date]: sameDate};
});
console.log(dateToTransactions);
I would do something like this:
const days = [];
for (let i = 0; i < transactions.length; i++) {
transactions[i].day = transactions[i].receiveDate || transactions[i].paidDate;
days.push(transactions[i].day);
}
const result = new Map();
days.forEach((day) => {
result.set(day, [])
});
transactions.forEach((transaction) => {
let r = result.get(transaction.day);
r.push(transaction);
result.set(transaction.day, r);
});
Then, in the result map you have a list of the transactions that were made for each day.
This will give the result you expect
const days = {};
const finalArray = transactions.forEach((transaction) => {
let date = (transaction.receiveDate || transaction.paidDate)
if (!days[date]) { days[date] = [transaction]}
else {days[date].push(transaction)}
});
console.log(days);

JavaScript: How to convert nested array of object to key-value pair objects

It can be duplicate question but i have tried a lot but i did not get expected result.Could some one help me.
I am getting an array in request body like :
[
{
"name":"array",
"book":[
{
"name":"name1",
"book":"book1"
},
{
"name":"name2",
"book":"book2"
}
]
},
{
"name":"name3",
"book":"book3"
}
]
And I need to convert the array of nested array to below format
{
array: [
{
name1: "book1"
},
{
name2: "book2"
}
],
name3: "book3"
}
Note:In some cases book can be array or string.
On my first attempt i have tried below code to convert it into single object but it doest not convert nested array to key value pair
const array=[
{
"name":"array",
"book":[
{
"name":"name1",
"book":"book1"
},
{
"name":"name2",
"book":"book2"
}
]
},
{
"name":"name3",
"book":"book3"
}
]
var result = {};
for (var i = 0; i < array.length; i++) {
result[array[i].name] = array[i].value;
}
console.log(result);
Response for the above code
{
array: [
{
name: "name1",
book: "book1"
},
{
name: "name2",
book: "book2"
}
],
name3: "book3"
}
EDITED
I have made little change in the Code from the Ahmed's answer and it worked
const res=[
{
"name":"array",
"book":[
{
"name":"name1",
"book":"book1"
},
{
"name":"name2",
"book":"book2"
}
]
},
{
"name":"name3",
"book":"book3"
}
]
const obj = {}
for(let i = 0 ; i < res.length; i++){
let name = res[i].name
if(Array.isArray(res[i]['book'])){
obj[name] = [];
for(let item in res[i]['book']){
let key = res[i]['book'][item]['name']
let value = res[i]['book'][item]['book']
let entry = {}
entry[key] = value
obj[name].push(entry)
}
}
else{
obj[res[i].name]=res[i].book;
}
}
console.log(obj);
The added snippet should solve your problem.
The problem in your code was Appropriate nesting you didn't access the wanted values and didn't handle all the cases Hence, The wrong output.
const res = [
{
"name":"array",
"book":[
{
"name":"name1",
"book":"book1"
},
{
"name":"name2",
"book":"book2"
}
]
},
{
"name":"name3",
"book":"book3"
}
]
const obj = {}
for(let i = 0 ; i < res.length; i++){
let name = res[i].name
if(Array.isArray(res[i]['book'])){
obj[name] = []
for(let item in res[i]['book']){
let key = res[i]['book'][item]['name']
let value = res[i]['book'][item]['book']
let entry = {}
entry[key] = value
obj[name].push(entry)
}
}
else{
obj[name] = res[i]['book']
}
}
for(let item in obj){
console.log(item)
console.log(obj[item])
}

Seperate values based on property value and show with javascript

I have an array that looks like this:
var array = [[
{ "loc": {} },
{ "distance": 6.4 },
{ "zip1": "06120" },
{ "zip2": "06095" },
{ "group": 1 },
{ "weight": 1119 }
], [
{ "loc": {} },
{ "distance": 6.41 },
{ "zip1": "06095" },
{ "zip2": "06120" },
{ "group": 2 },
{ "weight": 41976 }
], [
{ "loc": {} },
{ "distance": 6.41 },
{ "zip1": "06095" },
{ "zip2": "06120" },
{ "group": 1 },
{ "weight": 41976 }
]];
Now I want to take the array values based on the property values for show in HTML.
Expected output is split into array with "group" property. I also need to store in HTML with based on group, as shown in the example below:
group 1:
all zip1's under group 1
group 2:
all zip1's under group 2
I tried using a loop but I didn't manage to get the right answer:
for (var k = 0; k < array.length; k++) {
var array1 = array[k];
if (flag[array1[2]["zip1"]]) continue;
flag[array1[2]["zip1"]] = true;
output2.push(array1);
}
So help me to find split the array show in HTML with group wise
Using reduce, you can create an object with each group value as key and an array of zip1 as values like this:
Then loop through the Object.entries, to create the HTML:
const array = [[{"loc":{}},{"distance":6.4},{"zip1":"06120"},{"zip2":"06095"},{"group":1},{"weight":1119}],[{"loc":{}},{"distance":6.41},{"zip1":"06095"},{"zip2":"06120"},{"group":2},{"weight":41976}],[{"loc":{}},{"distance":6.41},{"zip1":"06095"},{"zip2":"06120"},{"group":1},{"weight":41976}]];
const merged = array.reduce((r, a) =>{
const { group } = a.find(n => n.group)
const { zip1 } = a.find(n => n.zip1)
r[group] = r[group] || []
r[group].push(zip1)
return r;
},{})
const output = document.getElementById('output');
Object.entries(merged).forEach(([group, zips]) => {
const h1 = document.createElement('h1');
h1.innerHTML = "group " + group
const span = document.createElement('span');
span.innerHTML = `Zip1 - ${zips} (in group - ${group})`;
output.appendChild(h1)
output.appendChild(span)
})
<div id="output"></div>

Categories

Resources