I have Object List Data.
I have to sort wise uniqueid by value. and their data store respective uniqueid Object.
** Object List **
{
uniqueid : 200,
name : "sandesh",
loop: 222,
salary : 2500
},
{
uniqueid : 300,
name : "hello",
loop: 222,
salary : 2500
},
{
uniqueid : 300,
name : "hello1",
loop: 222,
salary : 2500
};
I will create an object uniqueid wise and Store there value but every data create duplicate object.
var newArray = [];
this.userBetHistory.forEach(item => {
var newItem = {uniqueid : item.uniqueid, BetData: []};
this.userBetHistory.forEach(innerItem => {
if(innerItem.uniqueid== item.uniqueid){
newItem.BetData = newItem.BetData.concat(innerItem);
}
});
newArray.push(newItem);
});
** Expected Output: **
{
uniqueid : 200,
data :
{
uniqueid : 200,
name : "sandesh",
loop: 222,
salary : 2500
}
},
{
uniqueid : 300,
data :
{
uniqueid : 300,
name : "hello",
loop: 222,
salary : 2500
},
{
uniqueid : 300,
name : "hello1",
loop: 222,
salary : 2500
}
}
You can use Array.reduce for formatting the data
let data = [{uniqueid:200,name:'sandesh',loop:222,salary:2500,},{uniqueid:300,name:'hello',loop:222,salary:2500,},{uniqueid:300,name:'hello1',loop:222,salary:2500,},]
const formattedData = (data) => {
const result = data.reduce((res, d) => {
if(res[d.uniqueid]) {
res[d.uniqueid].data.push(d);
} else {
res[d.uniqueid] = {
uniqueid: d.uniqueid,
data: [
{...d}
]
}
}
return res;
}, {}) ;
return Object.values(result);
}
console.log(formattedData(data))
Hope this is what the output that you are looking for
You can do it with some mapping and filtering.
const userBetHistory = [{uniqueid: 200,name: "sandesh",loop: 222,salary: 2500,},{uniqueid: 300,name: "hello",loop: 222,salary: 2500,},{uniqueid: 300,name: "hello1",loop: 222,salary: 2500, }];
let tempData = userBetHistory.map((activeBet) => {
const activeBetSubData = userBetHistory.filter(
(bet) => bet.uniqueid === activeBet.uniqueid
);
return {
uniqueid: activeBetSubData[0].uniqueid,
data: activeBetSubData,
};
});
tempData = tempData
.map((item) => item.uniqueid)
.map((item, i, final) => final.indexOf(item) === i && i)
.filter((item) => tempData[item])
.map((item) => tempData[item]);
console.log(tempData);
Related
The code i tried
function findHighest(){
var highest = 0; // assum min 0
var highestItem;
$('tr').each(function(index, item){
if(index > 0){
var math = $(item).find('td').eq(1).text();
var eng = $(item).find('td').eq(2).text();
var lit = $(item).find('td').eq(3).text();
//alert(math)
var sum = parseFloat(math) + parseFloat(eng) + parseFloat(lit)
if (sum > highest){
highest = sum;
highestItem = item;
}
}
})
$(highestItem).css({ 'font-style': 'italic', 'color': 'red' });
}
I am trying to find name of student who got highest marks in class in at least two subjects in JavaScript?
const highestMarks=[];
const studentsWithHighestMarks=[];
const students = [{ name: "mini", subject: [{ maths : 20}, {english: 23}, { science: 25}, { sports: 24}] }, { name: "jerry", subject: [{ maths : 22}, {english: 20}, { science: 20}, { sports: 21}] }, { name: "john", subject: [{ maths : 23}, {english: 25}, { science: 20}, { sports: 21}] }];
students.forEach(student=>{
student.subject.forEach(subject=>{
for(let key in subject){
var index = highestMarks.findIndex(obj => {
return obj.subject === key
});
if (index===-1) {
highestMarks.push({
subject:key,
marks:subject[key],
students:[student.name]
})
}else if(highestMarks[index].marks<subject[key]){
highestMarks[index].marks=subject[key];
highestMarks[index].students=[student.name];
}
else if(highestMarks[index].marks==subject[key]){
highestMarks[index].marks=subject[key];
highestMarks[index].students.push(student.name);
}
}
})
});
students.forEach(student=>{
let count=0;
highestMarks.forEach(item=>{
if(item.students.includes(student.name)){
count++;
}
});
if(count>=2){
studentsWithHighestMarks.push(student.name)
}
})
console.log(studentsWithHighestMarks)
const subjectsConsidering = 2;
const getStudentMarks = (student) => {
const studentMarksList = [];
student.subject.forEach((subjectData) => {
studentMarksList.push(Object.values(subjectData)[0]);
});
const sum = studentMarksList.sort().reverse().reduce((sum, a, index) => {
// restrict only for first 2 subjects
if (index < subjectsConsidering) {
return sum + a;
}
return sum + 0;
});
return sum;
}
students.sort((studentA, studentB) => {
//return 0 for equal marks
return getStudentMarks(studentA) > getStudentMarks(studentB) ? -1 : 1;
});
console.log(students);
//This gives the sorted array of students having the highest marks in at least 2 subjects.
// Transform the data into a more manageable format
// { "subject": [["name", grade], ["name", grade], ["name", grade]] }
let transformed = students.reduce(
(data, student) => {
student.subject.forEach(subject => {
const key = keys(subject)[0];
const grade = [student.name, subject[key]];
if (!(key in data)) {
data[key] = [];
}
data[key].push(grade);
})
return data;
},
{}
)
// Utility function to compare grades
function gradeCompare(a, b) {
return a[1] > b[1] ? -1 : 1;
}
// List the top student in each subject
let names = Object.keys(transformed).map((subject) => {
return transformed[subject].sort(gradeCompare)[0][0];
});
// names :: [ "john", "john", "mini", "mini" ]
// Count the student names
let counts = names.reduce((acc, current) => {
acc[current] = (acc[current] || 0) + 1;
return acc;
}, {});
// counts :: { john: 2, mini: 2 }
// Find the maximum occurring count
let maxCount = Math.max(...Object.values(counts));
// maxCount :: 2
// Filter the keys that have that count
let topStudents = Object.keys(counts).filter(k => counts[k] === maxCount);
// topStudents :: [ "john", "mini" ]
I have this:
{ 'Payment' : {
'Referenced' : 'referenced payment',
'Conciliate' : 'conciliate payment',
'Multiple' : 'multiple payment'
}
}
but can change in all moment for random nodes or add more, like:
{ 'Payment' : {
'Referenced' : 'referenced payment',
'Conciliate' : 'conciliate payment',
'Multiple' : {
'mult1' : 'example1',
'mult2' : 'example1'
},
'Inventory' : {
'datastorage' : 'dt1'
}
}
All nodes can be asigned randomly, and I need to search by value, I can pass:
referenced payment
and need:
Payment/Referenced
or I send:
example1
and I need:
Payment/Multiple/mult1
I don't know if exist something like that.
// Function
const findPath = (obj, query) => {
const makeArray = (obj, path = []) => {
const pairs = Object.entries(obj);
return pairs.map(([key, value]) =>
typeof value === "object"
? makeArray(value, [...path, key])
: { path: [...path, key], value }
);
};
return (
makeArray(obj)
.flat(Infinity)
.find(({ path, value }) => value === query)?.path.join("/") ?? null
);
};
// Usage
const path1 = findPath(
{
Payment: {
Referenced: "referenced payment",
Conciliate: "conciliate payment",
Multiple: {
mult1: "example1",
mult2: {
test: 123,
},
},
Inventory: {
datastorage: "dt1",
},
},
},
123
);
const path2 = findPath(
{
Payment: {
Referenced: "referenced payment",
Conciliate: "conciliate payment",
Multiple: {
mult1: "example1",
},
Inventory: {
datastorage: "dt1",
},
},
},
"referenced payment"
);
console.log("123: " + path1);
console.log("referenced payment: " + path2);
Explanation
The first step is converting the object into a linear array of the object tree and its paths. This is done recursively. Then, the array is flattened in order to be iterated through with Array.prototype.find, if the value matches the query, the path is returned, if no match was found it returns null.
Credits
Thanks to #Bravo for suggesting path array instead of template literal
I have an object from user input. The keys to that object are separated by commas, and I just want to separate those keys and make the keys of the object.
The key_array below is dynamic from user input, generates a different array each time, below I give you an example.
I have shown the object in my code which you can see below. you can also see the output by running that code.
var main_array = {};
var key_array = {
'user,name' : 'user name',
'user,email' : 'Email address',
'order,id' : 123456,
'order,qty' : 2,
'order,total' : 300,
'order,product,0,name' : "product1",
'order,product,0,qty' : 1,
'order,product,0,price' : 100,
'order,product,1,name' : "product2",
'order,product,1,qty' : 1,
'order,product,1,price' : 200,
};
for (keys in key_array){
var value = key_array[keys];
// What do I do here to get the output I want?
main_array['[' + keys.split(",").join('][')+ ']'] = value;
}
console.log(main_array);
Running the code above will give you the following output which is incorrect. And the output I don't want.
{
[order][id]: 123456,
[order][product][0][name]: "product1",
[order][product][0][price]: 100,
[order][product][0][qty]: 1,
[order][product][1][name]: "product2",
[order][product][1][price]: 200,
[order][product][1][qty]: 1,
[order][qty]: 2,
[order][total]: 300,
[user][email]: "Email address",
[user][name]: "user name"
}
I want an output like JSON below, so please tell me how to do it.
{
"user":{
"email" : "Email address",
"name" : "user name"
},
"order":{
"id" : 123456,
"qty" : 2,
"total" : 300,
"product":[
{
"name" : "product1",
"price" : 100,
"qty" : 1
},{
"name" : "product2",
"price" : 200,
"qty" : 1
}
]
}
}
Note: Please do not use eval, as using eval in this way is terribly unreliable, bad work and unsafe. Because I get all my data from user input, the likelihood of abuse can increase.
Use Object.entries to go over key and values of object.
Split the key by , separator and then build the object.
While building object, make sure to merge the keys and values using mergeTo method.
Then convert the objects which has the numerical keys then convert to object using convertObjsToArray method.
var key_array = {
"user,name": "user name",
"user,email": "Email address",
"order,id": 123456,
"order,qty": 2,
"order,total": 300,
"order,product,0,name": "product1",
"order,product,0,qty": 1,
"order,product,0,price": 100,
"order,product,1,name": "product2",
"order,product,1,qty": 1,
"order,product,1,price": 200
};
const mergeTo = (target, obj) => {
Object.entries(obj).forEach(([key, value]) => {
if (typeof value === "object" && !Array.isArray(value)) {
if (!target[key]) {
target[key] = {};
}
mergeTo(target[key], obj[key]);
} else {
target[key] = value;
}
});
};
const convertObjsToArray = obj => {
Object.entries(obj).forEach(([key, value]) => {
if (typeof value === "object") {
if (Object.keys(value).every(num => Number.isInteger(Number(num)))) {
obj[key] = Object.values(value);
} else {
convertObjsToArray(obj[key]);
}
}
});
};
const res = {};
Object.entries(key_array).map(([key, value]) => {
const keys = key.split(",");
let curr = { [keys.pop()]: value };
while (keys.length > 0) {
curr = { [keys.pop()]: curr };
}
mergeTo(res, curr);
});
convertObjsToArray(res);
console.log(res);
You can create the objects and keys required from the string dynamically, take each key and split it to an array using split(','). Using each item in the array create the structure required. Assuming if a key is a number, then it's parent must be an array.
Object.keys(key_array).forEach(key => {
const path = key.split(',');
let current = main_array;
for (let i = 0; i < path.length - 1; i++) {
if (!current[path[i]]) {
current[path[i]] = path[i + 1] && !isNaN(path[i + 1]) ? [] : {};
}
current = current[path[i]];
}
current[path.pop()] = key_array[key];
});
console.log(main_array); // Desired result
I have two variables which is an array and array of object, I want to add the value of first variable(distance) to second variable(list)
The following works fine, but I want to know if there's any other method to get some result.
let distance = [100,200,300]
let list = [ {"city" : "paris"} , {"city" : "london"} , { "city" : "barcelona" }]
for(let i = 0; i < distance.length;i++){
let listDistance = list.map(el => {
return Object.assign({}, el, {distance:distance[i++]})
return el
});
console.log(listDistance)
}
// output [ {city : paris , distance : 100 } , {city : london , distance : 200 } , { city : barcelona , distance : 300 }]
Like this?
let distance = [100,200,300]
let list = [ {"city" : "paris"} , {"city" : "london"} , { "city" : "barcelona" }]
list.forEach((city,i) => city.distance = distance[i])
console.log(list)
Older browsers
let distance = [100,200,300]
let list = [ {"city" : "paris"} , {"city" : "london"} , { "city" : "barcelona" }]
list.forEach(function(city,i) { city.distance = distance[i] })
console.log(list)
If you need a new Array you can use map:
const distance = [100,200,300]
let list = [ {"city" : "paris"} , {"city" : "london"} , { "city" : "barcelona" }]
let distList = list.map((city,i) => ({ ...city, distance : distance[i]}) )
console.log(distList)
Try this:
let array1 = [100, 200, 300]
let array2 = [{ "city": "paris" }, { "city": "london" }, { "city": "barcelona" }]
let res = array2.map((value, index) => {
return { ...value, distance: array1[index] }
})
console.log(res);
const listWithDistances = list.map(
(item, index) => ({ ...item, distance: distance[index] })
)
This has the same result of your example of returning a new Array of new Objects.
Try this
for(let i = 0; i < distance.length; i++)
{
list[i].distance = distance[i];
}
What would be the best way to remove any additional properties from an object that is not defined in defaults object?
var
defaults = {
color : 'blue',
size: 9,
price : 40.00,
instock : true
},
newItem = {
color: 'red',
size : 4,
price : 20.00
extra : invalid // discard this
extra1 : invalid // discard this
},
item = $.extend( defaults, newObject ) ;
Desired output....
{
color : 'red',
size: 4,
price : 20.00,
instock : true
}
You could reduce Object.keys(defaults) to an object containing either the override value or the default value:
var defaults = {
color : 'blue',
size: 9,
price : 40.00,
instock : true
},
newItem = {
color: 'red',
size : 4,
price : 20.00,
extra : 'invalid',
extra1 : 'invalid'
};
function getOverrides(defaults, obj) {
return Object.keys(defaults).reduce(function(result, cur) {
result[cur] = cur in obj ? obj[cur] : defaults[cur];
return result;
}, {});
}
console.log(getOverrides(defaults, newItem));
According to this performance comparison:
https://jsperf.com/dictionary-contains-key
The most efficient way to do this is:
for(attr in newItem) {
if(defaults[attr] === undefined)
delete newItem[attr];
}
Before you call $.extend, put the following.
for(variable in newItem) {
if(!(variable in defaults)) {
delete newItem[variable];
}
}
This will loop over every key in newItem and check that it is also a key in defaults. Note that this will modify newItem, so if that is not desired, you'll need to do some tweaking.
Only merge properties which existing in defaults object: (simple and supports old browsers)
var defaults = {
color : 'blue',
size: 9,
price : 40.00,
instock : true
};
var newItem = {
color: 'red',
size : 4,
price : 20.00,
extra : 'invalid', // discard this
extra1 : 'invalid' // discard this
};
var result = {};
for (var i in defaults) {
result[i] = newItem.hasOwnProperty(i) ? newItem[i] : defaults[i];
}
console.log(result);
Some code that I have been playing with that may be of interest, and an example of how to use it with your question.
'use strict';
var slice = Function.call.bind(Array.prototype.slice);
var reflectAssign = function assign(target) {
return slice(arguments, 1).every(function(source) {
if (source == null) {
return true;
}
var object = Object(source);
return Reflect.ownKeys(object).every(function(key) {
return Reflect.set(target, key, object[key]);
});
});
};
var reflectAssignHas = function(target) {
var targetKeys = Reflect.ownKeys(target);
return slice(arguments, 1).every(function(source) {
if (source == null) {
return true;
}
var object = Object(source);
return targetKeys.every(function(key) {
return Reflect.has(object, key) ? Reflect.set(target, key, object[key]) : true
});
});
};
var defaults = {
color: 'blue',
size: 9,
price: 40.00,
instock: true
};
var newItem = {
color: 'red',
size: 4,
price: 20.00,
extra: 'invalid', // discard this
extra1: 'invalid' // discard this
};
var item = {};
console.log(reflectAssign(item, defaults));
console.log(reflectAssignHas(item, newItem));
console.log(item);
<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.9/es5-shim.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.9/es5-sham.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.35.3/es6-shim.js"></script>