It's a complicated scenario but will try to explain as much as possible. I have one object or arrays and one array. Now i have to compare selectedmodel values with mappedmodels, if the value(Case insensitive) matches with that object then fetch all the values of it and push it into selected model and combine both. Hope the example will clear what i am trying to achive.
var mappedModels = { 'CC605': ['cc605', 'CC605', 'cC605'], 'TC75X': ['TC75X'] };
var selectedModels = ['CC605', 'tc76'];
var desiredOutput = ["CC605", "tc76", "cc605", "cC605"];
I already wrote a solution to achieve it but i need a better code in terms of performance. Here is the solution:
function combineModelCases(selectedModels) {
const modelCases = [];
selectedModels.forEach(elm => {
const existingModels = mappedModels[elm.toUpperCase()];
if (existingModels) {
for (const key of existingModels) {
if (elm.toUpperCase() !== key) {
modelCases.push(key);
}
}
}
});
return selectedModels.concat(modelCases);
}
Here is Fiddle
I am using typescript and underscore js for your references. Any help would be very helpful.
You could use flatMap to get a flattened array of values for each key in selectedModels. Then, create a Set to get a unique collection models. Use Array.from() to convert the set to an array.
const mappedModels = { 'CC605': ['cc605', 'CC605', 'cC605'], 'TC75X': ['TC75X'] },
selectedModels = ['CC605', 'tc76'];
const models = selectedModels.flatMap(m => mappedModels[m] || []),
unique = Array.from(new Set([...selectedModels, ...models]));
console.log(unique)
you can do the following, :
var mappedModels = { 'CC605': ['cc605', 'CC605', 'cC605'], 'TC75X': ['TC75X'] };
var selectedModels = ['CC605', 'tc76'];
var desiredOutput;
function combineModelCases(selectedValue){
if(mappedModels.hasOwnProperty(selectedValue)){
desiredOutput = [... new Set([...mappedModels[selectedValue], ...selectedModels])]
return desiredOutput;
}
}
console.log(combineModelCases('CC605'));
here is the working demo : https://jsfiddle.net/wzo4d6uy/2/:
Related
Hi everyone I have object of object and I just want to combine data inside inner object in the form of array is there any way to that
input data
let data = {
ok123b:{
name:'shanu'
},
of123b:{
name:'rahul'
},
og1453jdfk:{
name:'ak'
},
ok1kjjdde23b:{
name:'man'
}
}
let arrayOfData =[data.ok123b.name,data.of123b.name,data.og1453jdfk.name,data.ok1kjjdde23b.name]
console.log(arrayOfData);
//this is hard coded i want dynamic code to convert data in the form of array
expected output
output = ['shanu','rahul','ak','man'];
There are several ways you can achieve this. I have updated my answer to include these.
Solution 1 (For loop and push() method)
You can use a simple for loop and push (add) each object's name to the array.
let data = {
ok123b:{name: 'shanu'},
of123b:{name: 'rahul'},
og1453jdfk:{name:'ak'},
ok1kjjdde23b:{name: 'man'}
}
let arrayOfData = [];
for(item in data) {
arrayOfData.push(data[item]['name'])
}
console.log(arrayOfData);
Solution 2 (Using Object.values() and map() method)
let data = {
ok123b:{name: 'shanu'},
of123b:{name: 'rahul'},
og1453jdfk:{name:'ak'},
ok1kjjdde23b:{name: 'man'}
}
let r = Object.values(data);
let result = r.map((element) => element.name)
console.log(result);
Solution 3 (One liner using Object.entries() and map() method)
let data = {
ok123b:{name: 'shanu'},
of123b:{name: 'rahul'},
og1453jdfk:{name:'ak'},
ok1kjjdde23b:{name: 'man'}
}
let result = Object.entries(data).map(a=>a[1].name)
console.log(result);
However as #Chris G mentioned, this is a very common question so you should probably browse similar questions such as:
Merge Objects
How can I merge properties of two JavaScript objects dynamically?
hi everyone if any one have same problem here is the solution
let data = {
ok123b:{
name:'shanu'
},
of123b:{
name:'rahul'
},
og1453jdfk:{
name:'ak'
},
ok1kjjdde23b:{
name:'man'
}
}
let r=Object.values(data);
let result =r.map((el) =>el.name)
console.log(result);
Suppose I have an array of object as:
const bookDetails = [{"author":"john","email":"john#gmail.com","readingTime":"121"},
{"author":"romero","email":"romero#gmail.com","readingTime":908},
{"author":"romero","email":"alpha#gmail.com","readingTime":1212},
{"author":"buck","email":"buck#gmail.com","readingTime":1902},
{"author":"buck","email":"bujor#gmail.com","readingTime":12125},
{"author":"romero","email":"romero#gmail.com","readingTime":500},
{"author":"john","email":"john#gmail.com","readingTime":10},
{"author":"legend","email":"legend#gmail.com","readingTime":12}
{"author":"john","email":"john#gmail.com","readingTime":1890}]
I have an object as:
const toMatch = {"romero#gmail.com":1212,"john#gmail.com":1248,"bujor#gmail.com":909}
I want to replace emailId with corresponding author.
So my expected O/P should be: {"romero":1212,"john":1248,"buck":909}
If anyone needs any further information please let me know.
You can generate a new object by iterating over bookDetails and look up the values from toMatch
Like this
const bookDetails=[{"author":"john","email":"john#gmail.com","readingTime":"121"},{"author":"romero","email":"romero#gmail.com","readingTime":908},{"author":"romero","email":"alpha#gmail.com","readingTime":1212},{"author":"buck","email":"buck#gmail.com","readingTime":1902},{"author":"buck","email":"bujor#gmail.com","readingTime":12125},{"author":"romero","email":"romero#gmail.com","readingTime":500},{"author":"john","email":"john#gmail.com","readingTime":10},{"author":"legend","email":"legend#gmail.com","readingTime":12},{"author":"john","email":"john#gmail.com","readingTime":1890}]
const toMatch = {"romero#gmail.com":1212,"john#gmail.com":1248,"bujor#gmail.com":909}
const result = {};
for (const detail of bookDetails) {
const {email, author} = detail;
if (email in toMatch) {
result[author] = toMatch[email];
}
}
console.log(result);
Ah, you want to matching names from emails based on the array of objects. Is that right? If so..
const bookDetails=[{"author":"john","email":"john#gmail.com","readingTime":"121"},{"author":"romero","email":"romero#gmail.com","readingTime":908},{"author":"romero","email":"alpha#gmail.com","readingTime":1212},{"author":"buck","email":"buck#gmail.com","readingTime":1902},{"author":"buck","email":"bujor#gmail.com","readingTime":12125},{"author":"romero","email":"romero#gmail.com","readingTime":500},{"author":"john","email":"john#gmail.com","readingTime":10},{"author":"legend","email":"legend#gmail.com","readingTime":12},{"author":"john","email":"john#gmail.com","readingTime":1890}]
function namesMap(object,list){
//to save complexity(assuming the array is huge), I'd just loop through the list once to get the data I need
var obj={} //relates emails to names
list.forEach(item=>{
obj[item.email]=item.author
})
var toReturn={}
Object.keys(object).forEach(email=>{
toReturn[obj[email]]=object[email] //email to name conversion
})
return toReturn
}
//example usage
const toMatch = {"romero#gmail.com":1212,"john#gmail.com":1248,"bujor#gmail.com":909}
console.log(namesMap(toMatch,bookDetails))
There you go, I'm 100% you can do this easier, but this is the fastest response that came to my mind:
function changeData(bookDetails){
let returnableObject = {};
bookDetails.forEach(book => {
returnableObject[book.author] = book.readingTime
})
return returnableObject;
}
*EDIT -> This would work if your Author name IS UNIQUE if the author name is not unique you should change the name or maybe use an array of objects, not an object with multiple values...
*EDIT 2 -> I think I didnt understand your question.
I'm trying to match and group objects, based on a property on each object, and put them in their own array that I can use to sort later for some selection criteria. The sort method isn't an option for me, because I need to sort for 4 different values of the property.
How can I dynamically create separate arrays for the objects who have a matching property?
For example, I can do this if I know that the form.RatingNumber will be 1, 2, 3, or 4:
var ratingNumOne = [],
ratingNumTwo,
ratingNumThree,
ratingNumFour;
forms.forEach(function(form) {
if (form.RatingNumber === 1){
ratingNumOne.push(form);
} else if (form.RatingNumber === 2){
ratingNumTwo.push(form)
} //and so on...
});
The problem is that the form.RatingNumber property could be any number, so hard-coding 1,2,3,4 will not work.
How can I group the forms dynamically, by each RatingNumber?
try to use reduce function, something like this:
forms.reduce((result, form) => {
result[form.RatingNumber] = result[form.RatingNumber] || []
result[form.RatingNumber].push(form)
}
,{})
the result would be object, with each of the keys is the rating number and the values is the forms with this rating number.
that would be dynamic for any count of rating number
You could use an object and take form.RatingNumber as key.
If you have zero based values without gaps, you could use an array instead of an object.
var ratingNumOne = [],
ratingNumTwo = [],
ratingNumThree = [],
ratingNumFour = [],
ratings = { 1: ratingNumOne, 2: ratingNumTwo, 3: ratingNumThree, 4: ratingNumFour };
// usage
ratings[form.RatingNumber].push(form);
try this its a work arround:
forms.forEach(form => {
if (!window['ratingNumber' + form.RatingNumber]) window['ratingNumber' + form.RatingNumber] = [];
window['ratingNumber' + form.RatingNumber].push(form);
});
this will create the variables automaticly. In the end it will look like this:
ratingNumber1 = [form, form, form];
ratingNumber2 = [form, form];
ratingNumber100 = [form];
but to notice ratingNumber3 (for example) could also be undefined.
Just to have it said, your solution makes no sense but this version works at least.
It does not matter what numbers you are getting with RatingNumber, just use it as index. The result will be an object with the RatingNumber as indexes and an array of object that have that RatingNumber as value.
//example input
var forms = [{RatingNumber:5 }, {RatingNumber:6}, {RatingNumber:78}, {RatingNumber:6}];
var results = {};
$.each(forms, function(i, form){
if(!results[form.RatingNumber])
results[form.RatingNumber]=[];
results[form.RatingNumber].push(form);
});
console.log(results);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
HIH
// Example input data
let forms = [{RatingNumber: 1}, {RatingNumber: 4}, {RatingNumber: 2}, {RatingNumber: 1}],
result = [];
forms.forEach(form => {
result[form.RatingNumber]
? result[form.RatingNumber].push(form)
: result[form.RatingNumber] = [form];
});
// Now `result` have all information. Next can do something else..
let getResult = index => {
let res = result[index] || [];
// Write your code here. For example VVVVV
console.log(`Rating ${index}: ${res.length} count`)
console.log(res)
}
getResult(1)
getResult(2)
getResult(3)
getResult(4)
Try to create an object with the "RatingNumber" as property:
rating = {};
forms.forEach(function(form) {
if( !rating[form.RatingNumber] ){
rating[form.RatingNumber] = []
}
rating[form.RatingNumber].push( form )
})
My data is in the following format..
var data= [['typeName', 'valueName'], ['type1', 'value1'],
['type1', 'value2'],['type2', 'value3'],['type2', 'value4']]
I wish to transform the above data to data as below..
var resultdata=[{'typeName':'type1','valueName':['value1','value2']},
{'typeName':'type2','valueName':['value3','value4']}]
Basically I pick up distinct 'typeName' values and then group 'valueName' values by 'typeName' values.
I would preferably use only knockoutjs, lodash or underscorejs as my soln already uses them but I'm open to other solutions as well..
All help is sincerely appreciated
Thanks
I think this solution using underscore should do the trick:
var result= _.chain(data)
.rest()
.groupBy( value => value[0])
.map( (value,key) => ({ [data[0][0]]: key, [data[0][1]]: _.map(value, val => val[1])}))
.value();
This solution uses rest to skip the first item in the data array (the type descriptors). The array is then grouped by the first value in the array (the type) and the mapping returns the grouping in the required form using es6 object initializer notation.
Given the result as:
var resultdata=[
{'typeName':'type1'},{'valueName':['value1','value2']},
{'typeName':'type2'},{'valueName':['value3','value4']}
]
I'm going to call 'typeName' the category and 'valueName' the items.
Since the original data look like this:
var data= [
['typeName', 'valueName'],
['type1', 'value1'],
['type1', 'value2'],
['type2', 'value3'],
['type2', 'value4']
]
It is clear there is a pattern. The first row of data is what we'll use as labels for category and items. All the remaining data represent the values being used inside category and items.
The first step is to extract the labels:
var categoryLabel = data[0][0];
var itemLabel = data[0][1];
Next, the unique categories will need to be determined, so we'll use reduce to build an array of unique categories:
var categories = data
.filter(function(row, i) { return i > 0 }) // remove the labels
.reduce(function(arrCategories, currRow) {
// Add the current rows' category if it doesn't already exist
var currCategory = currRow[0];
if (arrCategories.indexOf(currCategory) === -1) {
return arrCategories.concat(currCategory);
}
return arrCategories;
}, [])
Now that you have a set of categories, you just need to iterate over each one to find all items that belong to it:
var valuesByCategory = {};
categories.forEach(function(category) {
// find all the data items that match the category
var items = data
.filter(function(row) { return row[0] === category; })
.reduce(function(arrItems, currRow) {
var currItem = currRow[1];
if (arrItems.indexOf(currItem) === -1) {
return arrItems.concat(currItem);
}
return arrItems;
}, []);
valuesByCategory[category] = items;
});
Now that all the data has been parsed out, the only thing left to do is build the resultant array:
var resultdata = [];
// iterate through each of the categories
categories.forEach(function(category) {
// using the category label, output an object with the label and category
var categoryObj = {};
categoryObj[categoryLabel] = category;
resultdata.push(categoryObj);
// Next, create a items object containing all the values
var itemsObj = {};
itemsObj[itemLabel] = valuesByCategory[category];
resultdata.push(itemsObj);
}
and that's it :)
The best part is that you don't need any external libraries. This is all ES2015 javascript!
Here is a lodash version of Gruff Bunnies solution:
var data= [['typeName', 'valueName'], ['type1', 'value1'], ['type1', 'value2'],['type2', 'value3'],['type2', 'value4']]
var names = data[0]
var values = _.tail(data)
console.log(JSON.stringify(
_(values)
.groupBy(0)
.map( (value, key) => ({ [names[0]]: key, [names[1]]: _.map(value, 1)}) )
.value()
))
https://jsfiddle.net/nmf1fdf5/
I have the following JSON -
{
"node1":[
{
"one":"foo",
"two":"foo",
"three":"foo",
"four":"foo"
},
{
"one":"bar",
"two":"bar",
"three":"bar",
"four":"bar"
},
{
"one":"foo",
"two":"foo",
"three":"foo",
"four":"foo"
}
],
"node2":[
{
"link":"baz",
"link2":"baz"
},
{
"link":"baz",
"link2":"baz"
},
{
"link":"qux",
"link2":"qux"
},
]
};
I have the following javascript that will remove duplicates from the node1 section -
function groupBy(items, propertyName) {
var result = [];
$.each(items, function (index, item) {
if ($.inArray(item[propertyName], result) == -1) {
result.push(item[propertyName]);
}
});
return result;
}
groupBy(catalog.node1, 'one');
However this does not account for dupicates in node2.
The resulting JSON I require is to look like -
{
"node1":[
{
"one":"foo",
"two":"foo",
"three":"foo",
"four":"foo"
},
{
"one":"bar",
"two":"bar",
"three":"bar",
"four":"bar"
}
],
"node2":[
{
"link":"baz",
"link2":"baz"
},
{
"link":"qux",
"link2":"qux"
},
]
};
However I cannot get this to work and groupBy only returns a string with the duplicates removed not a restructured JSON?
You should probably look for some good implementation of a JavaScript set and use that to represent your node objects. The set data structure would ensure that you only keep unique items.
On the other hand, you may try to write your own dedup algorithm. This is one example
function dedup(data, equals){
if(data.length > 1){
return data.reduce(function(set, item){
var alreadyExist = set.some(function(unique){
return equals(unique, item);
});
if(!alreadyExist){
set.push(item)
}
return set;
},[]);
}
return [].concat(data);
}
Unfortunately, the performance of this algorithm is not too good, I think somewhat like O(n^2/2) since I check the set of unique items every time to verify if a given item exists. This won't be a big deal if your structure is really that small. But at any rate, this is where a hash-based or a tree-based algorithm would probably be better.
You can also see that I have abstracted away the definition of what is "equal". So you can provide that in a secondary function. Most likely the use of JSON.stringify is a bad idea because it takes time to serialize an object. If you can write your own customized algorithm to compare key by key that'd be probably better.
So, a naive (not recommended) implementation of equals could be somewhat like the proposed in the other answer:
var equals = function(left, right){
return JSON.stringify(left) === JSON.stringify(right);
};
And then you could simply do:
var res = Object.keys(source).reduce(function(res, key){
res[key] = dedup(source[key], equals);
return res;
},{});
Here is my version:
var obj = {} // JSON object provided in the post.
var result = Object.keys(obj);
var test = result.map(function(o){
obj[o] = obj[o].reduce(function(a,c){
if (!a.some(function(item){
return JSON.stringify(item) === JSON.stringify(c); })){
a.push(c);
}
return a;
},[]); return obj[o]; });
console.log(obj);//outputs the expected result
Using Array.prototype.reduce along with Array.prototype.some I searched for all the items being added into the new array generated into Array.prototype.reduce in the var named a by doing:
a.some(function(item){ return JSON.stringify(item) === JSON.stringify(c); })
Array.prototype.some will loop trough this new array and compare the existing items against the new item c using JSON.stringify.
Try this:
var duplicatedDataArray = [];
var DuplicatedArray = [];
//Avoiding Duplicate in Array Datas
var givenData = {givenDataForDuplication : givenArray};
$.each(givenData.givenDataForDuplication, function (index, value) {
if ($.inArray(value.ItemName, duplicatedDataArray) == -1) {
duplicatedDataArray.push(value.ItemName);
DuplicatedArray.push(value);
}
});