Extract properties from deleted/duplicated objects then assign to other objects - javascript

I need a little help here, y have this array:
[
{Code:13938, Country:699, Name:"Crocs", codeProduct:1}
{Code:13952, Country:699, Name:"Polo Club", codeProduct:14}
{Code:13952, Country:699, Name:"Polo Club", codeProduct:1}
{Code:13952, Country:699, Name:"Polo Club", codeProduct:3}
{Code:13953, Country:699, Name:"OZ", codeProduct:12}
....
]
And I need to convert to this:
[
{Code:13938, Country:699, Name:"Crocs", codeProduct:1}
{Code:13952, Country:699, Name:"Polo Club", codeProduct:"14, 1, 3" }
{Code:13953, Country:699, Name:"Polo Club", codeProduct:12}
]
I have no problem removing the duplicate objects, and getting the values of those delted objects.
var prodArray = [];
function uniq_fast(a) {
var seen = {};
var out = [];
var len = a.length;
var j = 0;
for(var i = 0; i < len; i++) {
var item = a[i].Codigo;
if(seen[item] !== 1) {
seen[item] = 1;
out[j++] = a[i];
}else{
prodArray.push({Code:item, codeProduct:a[i].TipoProductoCodigo});
}
}
return out;
}
this return a new array of objects whitout the repited values and add to a new array prodArray the properties of deleted ones.
// out return this:
[
{Code:13938, Country:699, Name:"Crocs", codeProduct:1}
{Code:13952, Country:699, Name:"Polo Club", codeProduct:"14, 1, 3" }
{Code:13953, Country:699, Name:"Polo Club", codeProduct:12}
]
and prodArr return this:
[
{Code:13952, codeProduct:1}
{Code:13952, codeProduct:3}
]
But how do i set the properties in prodArray in to the new one array that holds the no duplicate objects?.
Hope i have been clear

You could use a hash table as reference to the Code.
var data = [{ Code: 13938, Country: 699, Name: "Crocs", codeProduct: 1 }, { Code: 13952, Country: 699, Name: "Polo Club", codeProduct: 14 }, { Code: 13952, Country: 699, Name: "Polo Club", codeProduct: 1 }, { Code: 13952, Country: 699, Name: "Polo Club", codeProduct: 3 }, { Code: 13953, Country: 699, Name: "OZ", codeProduct: 12 }],
grouped = [];
data.forEach(function (a) {
if (!this[a.Code]) {
this[a.Code] = { Code: a.Code, Country: a.Country, Name: a.Name, codeProduct: a.codeProduct };
grouped.push(this[a.Code]);
return;
}
this[a.Code].codeProduct += ', ' + a.codeProduct;
}, Object.create(null));
console.log(grouped);

I'll try my best to answer this without fully understanding what you're attempting to do...
So you have your duplicate values in prodArray, great. Now you want them to be placed back into the array you just removed them from? Sure. To append an element to the end of an array, you use the push method.
I'm assuming the thing that you're caught up on is grabbing those missing JSON properties, Country and Name, and adding them back to the elements in prodArray. But since we know that Code is the same, we can use that to find the "missing" values. So here's how I'd do it, assuming a is your original array:
for (var i in prodArray) {
// find the duplicate in the orginal array
for (var j in a) {
if (a[j].Code == prodArray[i].Code) {
// found it, now append into a
a.push(a[j]);
break;
}
}
}
Am I close?

Related

Best way to merge two objects on a matching key-value pair

I'm having trouble making two objects into one on a matching key.
I have two objects coming from 2 apis and there is one matching key in the objects.
I want to iterate over them and if the storeId matches in both objects, I want to merge the two together as seen in the perfectObject.
I have tried the spread operator, Object.assign, for...in loop instead of the for loop seen here, but found close to none success.
Thanks for the help!
const logistics = [{
logisticsId: "L5E69E26D8FCAE",
storeId: 409388,
logisticsDate: "2020-03-12T07:19:09.000Z",
}, ];
const stores = [{
storeId: 409388,
ka: 0,
country: "ru",
name: "test",
city: "Moscow",
cxw: 1,
cx: 1,
plz: 22448,
}, ];
const perfetObject = {
storeId: 409388,
ka: 0,
country: "ru",
name: "test",
city: "Moscow",
cxw: 1,
cx: 1,
plz: 22448,
"storeId": 409388,
logisticsId: "L5E69E26D8FCAE",
storeId: 409388,
logisticsDate: "2020-03-12T07:19:09.000Z",
};
"logisticsId": "L5E69E26D8FCAE",
let d = {};
}
for (let i = 0; i < logistics.length; ++i) {
for (let k = 0; k < stores.length; ++k) {
if (logistics.storeId === stores.storeId) {
d = {
...stores.name,
...stores.city,
...logistics.logisticsId,
};
}
}
let d = {}
console.log(d);
Leaving aside the nested for loop (there are better data structures for you to take advantage of that make this unnecessary), the easiest method would be to use Object.assign() or the spread operator, especially if the key names are guaranteed to never conflict.
const logistics = [{
logisticsId: "L5E69E26D8FCAE",
storeId: 409388,
logisticsDate: "2020-03-12T07:19:09.000Z",
}, ];
const stores = [{
storeId: 409388,
ka: 0,
country: "ru",
name: "test",
city: "Moscow",
cxw: 1,
cx: 1,
plz: 22448,
}, ];
for (let i = 0; i < logistics.length; ++i) {
for (let k = 0; k < stores.length; ++k) {
if (logistics[i].storeId === stores[k].storeId) {
console.log(Object.assign({}, logistics[i], stores[k]));
}
}
}
This assumes all store IDs are valid (e.g. have the expected store data) and all logistics elements have a valid store defined.
This is a working example answer from a reddit user u/albedoa:
const storesByStoreId = stores.reduce(
(obj, store) => {
if (!obj.hasOwnProperty(store.storeId)) {
obj[store.storeId] = store;
}
return obj;
},
{}
);
const perfectArray = logistics.map(logistic => ({
...storesByStoreId[logistic.storeId],
...logistic
}));
This way, it combines the two as supposed to, or returns the object itself if there is no match.

Combine the result of two input fields with JavaScript?

I have as a result from an input form a couple of strings and I want them to convert them, so they fit as data for my ajax-request. I am looking for an easy way, but I can't get it right. Basically I want to convert/map this array:
[
{ name: "[1][apples]", value: "2" }
{ name: "[1][melons]", value: "1" }
{ name: "[2][apples]", value: "2" }
{ name: "[2][melons]", value: "4" }
{ name: "[3][apples]", value: "3" }
{ name: "[3][melons]", value: "2" }
]
into
[{"id": 1, "apples": 2, "melons": 1}, {"id": 2, "apples": 2, "melons": 4}, {...}]
Any idea? I would appreciate some hint? I could't not find an easy solution via html though.
Thanks
you can use a for loop to access each element and display them.
Refer to this link. For loop in multidimensional javascript array
Firstly, I have replaced the square brackets using a regular expression and formed a new array. After that, I have merged object having same ID using spread operator.
You can refer to the code below which solves this problem.
let array = [
{ name: "[1][apples]", value: "2" },
{ name: "[1][melons]", value: "1" },
{ name: "[2][apples]", value: "2" },
{ name: "[2][melons]", value: "4" },
{ name: "[3][apples]", value: "3" },
{ name: "[3][melons]", value: "2" }];
let newArray = [];
let result = [];
array.forEach((obj, i) => {
let nameArray = obj.name.replace(/[\[\]']+/g, ' ').trim().split(' ');
let o = {};
o['id'] = parseInt(nameArray[0]);
o[nameArray[1]] = obj.value;
newArray.push(o);
});
for(let i = 0; i< newArray.length; i++) {
for(let j = i+1; j < newArray.length; j++) {
if(newArray[i].id === newArray[j].id) {
let o = {...newArray[i], ...newArray[j]};
result.push(o);`enter code here`
}
}
}
console.log('Final result', result);
Thanks for the input. I think my question needed to be more specific:
(1) Yes, they are always in order.
(2) My names of my input-tags in html appear to be an multidimensional array. This is not the case! I tried something, but it turned out to be for php.
I found the follow workaround:
function apiAdapter() {
var arrayToCopy = $("#formsteps").serializeArray();
var copiedArray = [];
for (let i = 0; i < arrayToCopy.length; i += 2) {
var id = arrayToCopy[i].name.slice(arrayToCopy[i].name.indexOf('[') + 1, arrayToCopy[i].name.indexOf(']'));
copiedArray.push({ "id": id, "apples": arrayToCopy[i].value, "melons": arrayToCopy[i + 1].value })
}
return copiedArray;
}
As I am new to JavaScript I always look for better solutions. So thanks again for your posts.

Filter the object depending on the field's value in javascript

I'm kinda new to javascript. Here I have the following object:
obj = {
0:{id:1, location: loc1, title:title1},
1:{id:2, location: loc2, title:title2},
2:{id:3, location: loc1, title:title3},
3:{id:4, location: loc3, title:title4},
4:{id:5, location: loc1, title:title5}
}
What I need is to filter the object by location depending on its value and create a new object like the following:
obj = {
loc1:{
0:{id:1, location: loc1, title:title1},
1:{id:3, location: loc1, title:title3},
2:{id:5, location: loc1, title:title5}
},
loc2:{
0:{id:2, location: loc2, title:title2}
}
loc3:{
0:{id:4, location: loc3, title:title4}
}
}
How can I achieve the above object?
I tried using for and push to a new array but the location should be dynamic and may change in the future and I want to have one object to manage like above.
var theLoc1 = [], theLoc2 = [];
for(var i = 0; i < response.length; i++) {
if(response[i].location == 'loc1'){
theLoc1.push(response[i]);
}else if(response[i].location == 'loc2'){
theLoc2.push(response[i]);
}
}
This Code is what u really need:
obj = [
{ id: 1, location: 'loc1', title: 'title1' },
{ id: 2, location: 'loc2', title: 'title2' },
{ id: 3, location: 'loc1', title: 'title3' },
{ id: 4, location: 'loc3', title: 'title4' },
{ id: 5, location: 'loc1', title: 'title5' }
];
var locations = {};
for (var i = 0; i < obj.length; i++) {
locations[obj[i].location] = [];
}
console.log(locations);
for (var i = 0; i < obj.length; i++) {
locations[obj[i].location].push(obj[i]);
}
console.log(locations);
**Update:It Can be done in a single for loop but for simplicity reasons i wrote it like this. **
let obj;
for(var i = 0; i < response.length; i++) {
if( !Object.hasOwnProperty(obj, response[i].location)
{ obj[response[i].location] = []; }
obj[response[i].location].push(response[i]);
}
You can dynamically create JS object properties if you just address them. This means:
let obj = {};
obj.bark = "how-how";
console.log(obj.bark); // "how-how";
obj[bark2] = "waf-waf";
console.log(obj.bark2); // "waf-waf";
you can use it to struct your new object with the locations names, so even if someday you get "location999" it'll still work.
I put the if that checks if the object laready has that property because you want the property to be an array. If it wasn't you could've just put the value inside like in my example, but im not sure if push would work on it so I initialize it to be empty array just in case. You can check it yourself and ommit the if if its not needed.
My solution using functional programming.
const obj = {
0: { id: 1, location: 'loc1', title: 'title1' },
1: { id: 2, location: 'loc2', title: 'title2' },
2: { id: 3, location: 'loc1', title: 'title3' },
3: { id: 4, location: 'loc3', title: 'title4' },
4: { id: 5, location: 'loc1', title: 'title5' }
};
const result = Object.keys(obj).reduce((newObject, item) => {
const location = obj[item].location;
const index = newObject[location] ? Object.keys(newObject[location]).length : 0;
return {
...newObject,
[location]: {
...newObject[location],
[index]: obj[item]
}
};
}, {});
console.log(result);
In order to group your items by location you can iterate your array, see whether its location was already grouped and if not, create a new group for it. Afterwards add the item to the corresponding group.
var obj = [
{id: 1, location: "loc1", title: "title1"},
{id: 2, location: "loc2", title: "title2"},
{id: 3, location: "loc1", title: "title3"},
{id: 4, location: "loc3", title: "title4"},
{id: 5, location: "loc1", title: "title5"}
];
var formattedArray = new Array();
for (var i = 0; i < obj.length; i++) {
if (!formattedArray[obj[i].location]) {
formattedArray[obj[i].location] = new Array();
}
formattedArray[obj[i].location].push(obj[i]);
}
console.log(formattedArray);
JsFiddle example code:
JsFiddle
You can try the following if your loc1, loc2, loc3 are fixed. (That is what I understood after reading your query)
var response = [
{id:1, location: "loc1", title:"title1"},
{id:2, location: "loc2", title:"title2"},
{id:3, location: "loc1", title:"title3"},
{id:4, location: "loc3", title:"title4"},
{id:5, location: "loc1", title:"title5"}
]
var resObj = {
published:[],
private: [],
pending:[]
}
for(var i = 0; i < response.length; i++) {
if(response[i].location == 'loc1'){
resObj.published.push(response[i]);
}else if(response[i].location == 'loc2'){
resObj.private.push(response[i]);
}else {
resObj.pending.push(response[i]);
}
}
console.log(resObj)
I think the better way to do this, is to group your objects already in your backend. You can use the linq function .GroupBy(x => x.location).
This is near the same problem:
How to count rows of a table grouped by shortdatestring?
// create an array of arrays;
var groupOfLocations[];
// loop on your locations
for(var i = 0; i < response.length; i++) {
// push if already existing
for(var iGroup = 0; iGroup < groupOfLocations.length; iGroup++) {
if(groupOfLocations[iGroup][0].location == response[i].location) {
groupOfLocations[iGroup].push(response[i]); break;
}
// create a new array if not found
if(iGroup >= groupOfLocations.length) groupOfLocations.push(new array(response[i]));
}
May contains syntax mistakes, but the idea is here.

Convert object to JSON Array?

I have the following object being returned. I am counting a list of names by reading from a json file and storing the results in a new object.
{
ted: 501,
jeff: 40,
tony: 90
}
The following function creates an object with the names as properties and the count as their values.
function countNames(json){
var count = {};
for (var i = 0, j = json.length; i < j; i++) {
if (count[json[i].name]) {
count[json[i].name]++;
}
else {
count[json[i].name] = 1;
}
}
return count;
}
I need to create an array of objects that generate a result like this.
[
{
name: 'ted',
total: 501
},
{
name: 'jeff',
total: 40
}
{
name: 'tony',
total: 90
}
]
I am not sure what the best approach and most efficient way of achieving this is. Any help is appreciated.
Consider this following Javascript snippet:
for (var item in obj) {
result.push({
name: item,
total: obj[item]
});
}
Working DEMO
Output:
[
{
"name":"ted",
"total":501
},
{
"name":"jeff",
"total":40
},
{
"name":"tony",
"total":90
}
]
I don't understand how your code example relates to the question, but this turns the data in the first format into the last format:
var output = Object.keys(input).map(function(key) {
return {
name: key,
count: input[key]
}
});
it uses functional programming style, which usually leads to cleaner code.
JSBin

Updating an array of objects in javascript

I have an array of javascript objects like the following:
var food = [
{id: 1, name: 'Apples', owned: true },
{id: 2, name: 'Oranges', owned: false },
{id: 3, name: 'Bananas', owned: true }
];
Then I receive another array with the following data:
var newFood = [
{id: 1, name: 'Peas'},
{id: 2, name: 'Oranges'},
{id: 3, name: 'Bananas'},
{id: 4, name: 'Grapefruits'}
];
How can I update the previous food array with the new information in newFeed, without overwriting the original owned property, while adding an owned: false to any new object?
Keep in mind this is plain javascript, not jQuery.
You'd probably want to index food by id so make food an object instead of an array:
var food = {
1: {name: "Apples", owned: true},
//...
}
then iterate over newFood and update the fields appropriately.
I think you can use underscore.js for fix the problem.
var arrayObj = [
{Name:'John',LastName:'Smith'},
{Name:'Peter',LastName:'Jordan'},
{Name:'Mike',LastName:'Tyson'}
];
var element = _.findWhere(arrayObj, { Name: 'Mike' });
element.Name="SuperMike";
console.log(arrayObj);
This works:
var temp = {};
for (var i = 0, l = food.length; i < l; i += 1) {
temp[food[i].name] = true;
}
for (var i = 0, l = newFood.length; i < l; i += 1) {
if ( !temp[newFood[i].name] ) {
food.push( { id: food.length + 1, name: newFood[i].name, owned: false });
}
}
The first for statement will populate the temp object with the fruit names from the food array, so that we know which fruits exist in it. In this case, temp will be this:
{ "Apples": true, "Oranges": true, "Bananas": true }
Then, the second for statement checks for each fruit in newFood if that fruit exists in temp, and if it doesn't, if pushes a new array item into the food array.
some thing like this? JSFiddle Example
JavaScript
function updateFood( newFood, oldFood ) {
var foodLength = oldFood.length - 1;
for (var i = 0; i < newFood.length; i++) {
if (i > foodLength) { //add more if needed
newFood[i].owned = false;
oldFood.push(newFood[i]);
} else if (!food[i].owned) { //replace if needed
newFood[i].owned = false;
oldFood[i] = newFood[i];
}
}
}

Categories

Resources