programmatically add object properties of arrays - javascript

[
{
"uId": "2",
"tabId": 1,
"tabName": "Main",
"points": "10"
},
{
"uId": "3",
"tabId": 2,
"tabName": "Photography",
"points": "20"
}
]
how can I insert into specified array by inspecting its properties values? says I want to add a assoc object into uId = 3, how can I do that? or it's not possible technically?

This is also possible using array.map (Added to the ECMA-262 standard in the 5th edition):
array.map(function(i){
if(i.uId == 3) i['newprop'] = 'newValue';
});
Example Here.
Update: It could be an array
if(i.uId == 3) i['newprop'] = ['newvalue1', 'newvalue2'];
Example2 Here.

They look like JSON data , so json_decode() to an array , search for the UId value and then add the corresponding assoc value and after the end finally wrap them up using json_encode()
foreach($array as $k=>&$arr)
{
if($arr->{'uId'}==2)
{
$arr->{'somecol'}="Hey";
}
}
echo json_encode($array,JSON_PRETTY_PRINT);
OUTPUT :
[
{
"uId": "2",
"tabId": 1,
"tabName": "Main",
"points": "10",
"somecol": "Hey"
},
{
"uId": "3",
"tabId": 2,
"tabName": "Photography",
"points": "20"
}
]

var array = [
{
"uId": "2",
"tabId": 1,
"tabName": "Main",
"points": "10"
},
{
"uId": "3",
"tabId": 2,
"tabName": "Photography",
"points": "20"
}
];
for ( var i = 0; i < array.length; i++ ) {
if ( array[i].uId == 3) {
array[i].someProp = "Hello";
break; // remove this line for multiple updates
}
}
Or you can make a function like this:
function getMatch(data, uid) {
for ( var i = 0; i < data.length; i++ ) {
if ( data[i].uId == 3) {
return data[i];
}
}
}
and use it like this:
getMatch(array, 3).someproperty = 4;

You can use the map function, which executes a function on each element of an array
a.map(function(el) {
if (el.uId == 3) {
el.prop = "value";
}
});
Or you can use the filter function.
// Get the array of object which match the condition
var matches = a.filter(function(x) { return x.uId == 3 });
if (matches.length > 0) {
matches[0].prop = "value";
}

Related

Remove duplicate array from response comparing attribute value

I want to remove a duplicate array from the response on the basis of the attribute value. If the attribute_value data match with other array attribute value then other should be removed.
The logic is very simple. check duplicate attribute_value in each array and remove duplicate array and return
In response. now you can see the attribute value = 1 is thrice
and attribute value = 2 is twice
How do i compare and remove whole array if I see attribute value duplicate?
I tried with filter method which seems not working. Please help.
for(var j=0; j<social_post_link.length; j++){
newFilterarray = social_post_link[j].activity_attributes[0].attribute_value.filter(function(item, index) {
if (social_post_link[j].activity_attributes[0].attribute_value.indexOf(item) == index){
return social_post_link;
}
});
}
Response
[
{
"id": "484822",
"activity_attributes": [
{
"id": "868117",
"activity_id": "484822",
"attribute_name": "position",
"attribute_value": "1",
}
]
},
{
"id": "484884",
"activity_attributes": [
{
"id": "868175",
"activity_id": "484884",
"attribute_name": "position",
"attribute_value": "1",
}
]
},
{
"id": "484888",
"activity_attributes": [
{
"id": "868182",
"activity_id": "484888",
"attribute_name": "position",
"attribute_value": "1",
}
]
},
{
"id": "484823",
"activity_attributes": [
{
"id": "868120",
"activity_id": "484823",
"attribute_name": "position",
"attribute_value": "2",
}
]
},
{
"id": "484975",
"activity_attributes": [
{
"id": "868344",
"attribute_name": "position",
"attribute_value": "2",
}
]
},
{
"id": "484891",
"activity_attributes": [
{
"id": "868189",
"attribute_name": "position",
"attribute_value": "3",
}
]
},
{
"id": "484903",
"activity_attributes": [
{
"id": "868200",
"attribute_name": "position",
"attribute_value": "4",
},
]
}
]
Desired output
[
{
"id": "484822",
"activity_attributes": [
{
"id": "868117",
"activity_id": "484822",
"attribute_name": "position",
"attribute_value": "1",
}
]
},
{
"id": "484823",
"activity_attributes": [
{
"id": "868120",
"activity_id": "484823",
"attribute_name": "position",
"attribute_value": "2",
}
]
},
{
"id": "484891",
"activity_attributes": [
{
"id": "868189",
"attribute_name": "position",
"attribute_value": "3",
}
]
},
{
"id": "484903",
"activity_attributes": [
{
"id": "868200",
"attribute_name": "position",
"attribute_value": "4",
},
]
}
]
You can probably use the lodash utility uniqBy,
where iteratee is a function that returns the value you want to compare against.
In your case, it would probably look like the following:
const uniqueLinks = _.uniqBy(social_post_link, item =>
item.activity_attributes[0].attribute_value
)
Edit:
Here is a vanilla JS function that will accomplish the same.
const filterByIteratee = (array, iteratee) => {
// Empty object to store attributes as we encounter them
const previousAttributeNames = {
}
return array.filter(item => {
// Get the right value
const itemValue = iteratee(item)
// Check if we have already stored this item
if (previousAttributeNames.hasOwnProperty(itemValue)) return false
else {
// Store the item so next time we encounter it we filter it out
previousAttributeNames[itemValue] = true
return true
}
})
}
It will loop through an array, store its identifier by some function, and return only the first instance of each item.
Use it the same way:
const uniqueLinks = filterByIteratee(social_post_link, item =>
item.activity_attributes[0].attribute_value
)
This is probably not the best performing solution. but it works for your requirements.
var resultArray = [];
for (var i = 0; i < social_post_link.length; i++) {
var currentSocialLink = social_post_link[i];
for (var j = 0; j < currentSocialLink.activity_attributes.length; j++) {
if (!resultArray.some(val =>
val.activity_attributes.some(activity =>
activity.attribute_value === currentSocialLink.activity_attributes[j].attribute_value))) {
resultArray.push(currentSocialLink);
}
}
}
function removeDuplicates(myArr, prop) { // removes duplicate objects from array
return myArr.filter((obj, pos, arr) => {
return arr.map(mapObj => mapObj[prop]).indexOf(obj[prop]) === pos;
});
};
I found this function not too long ago which removes duplicate objects from an array. Pass it the array and the property you wish to not be duplicated.

Create array from complex array objects & loops in javascript

I currently have a complex orders array (coming from a JSON client) that contains multiple orders like this (contains 2):
0: {
"employee": "Nicole"
"total": 13
"lineItems": {
"elements": [2]
0: {
"name": "Burger"
"price": 8
}
1: {
"name": "Lamb"
"price": 6.50
}
}
}
1: {
"employee": "Dan"
"total": 11
"lineItems": {
"elements": [2]
0: {
"name": "Lamb"
"price": 4.50
}
1: {
"name": "Meatballs"
"price": 6.50
}
}
}
What I want to do is create a new array that loops through the above and creates new items array based on the name of the lineItems object above. i.e. final output looks something like this:
var items = {
"Burger" = {
"totalSpent" : 8
},
"Lamb" = {
"totalSpent" : 13
// Note this totalSpent is an iteration or sum of all "price" items where name/id = "Lamb"
},
"Meatballs" = {
"totalSpent" : 4.50
}
}
I'm more used to PHP and have tried a number of different versions of this but can't seem to get the desired output. Here's what I've got so far:
var orders = //As above//
// Initialising new array to hold my final values
var orderItems = [];
for (var i = 0, len = orders.length; i < len; i++){
for(var e = 0, leng = orders[i]['lineItems']['elements'].length; e < leng; e++){
var totalSpent = 0;
var id = orders[i]['lineItems']['elements'][e]['name'];
if (orders[id] in orderItems[id]){
// overwrite existing array item
orderItems[id]['totalSpent'] += orders[i]['lineItems']['elements'][e]['price'];
orderItems[id].push({totalSpent : orderItems[id]['totalSpent']});
}
else {
// Create new array item
orderItems.push(id);
orderItems[id].push({totalSpent : orders[i]['lineItems']['elements'][e]['price']});
}
}
}
Edit:
Had to correct your orders syntax, I added it to my answer so you can run the Javascript Snippet;
Changed the whole dot notation to bracket notation to make it easier to read and understand;
Corrected the bug about items remaining an empty array (it was in the inner for);
var orders = [
{
"employee": "Nicole",
"total": 13,
"lineItems": {
"elements": [
{
"name": "Burger",
"price": 8
},
{
"name": "Lamb",
"price": 6.50
}
]
}
},
{
"employee": "Dan",
"total": 11,
"lineItems": {
"elements": [
{
"name": "Lamb",
"price": 4.50
},
{
"name": "Meatballs",
"price": 6.50
}
]
}
}
];
var items = {};
// loop in orders array
for (var i = 0; i < orders.length; i++) {
var elements = orders[i]["lineItems"]["elements"];
// loop in orders[i]["lineItems"]["elements"] object
for (var eIndex in orders[i]["lineItems"]["elements"]) {
// Add new item if it doesn't already exist
if (!items.hasOwnProperty(elements[eIndex]["name"])) {
items[elements[eIndex]["name"]] = {"totalSpent": elements[eIndex]["price"]};
} else {
// If it exists, sum totalSpent
items[elements[eIndex]["name"]]["totalSpent"] += elements[eIndex]["price"];
}
}
}
console.log(items);
PS: To find out why I'm using bracket notation instead of dot notation, check this question, it's good to know!
First of all, there are some error in your order array, note the difference between {} (for objects) and []. Then it is just simple use of the map function to iterate over the arrays.
See your browser console (F12) for the result of this snippet
var orders = [{
"employee": "Nicole",
"total": 13,
"lineItems": {
"elements": [{
"name": "Burger",
"price": 8
}, {
"name": "Lamb",
"price": 6.50
}
]
}
}, {
"employee": "Dan",
"total": 11,
"lineItems": {
"elements": [{
"name": "Lamb",
"price": 6.50
}, {
"name": "Meatballs",
"price": 4.50
}]
}
}]
var items = {}
orders.map(function(order) {
order.lineItems.elements.map(function(elem) {
if (items[elem.name]) {
items[elem.name].totalSpent += elem.price
} else {
items[elem.name] = {"totalSpent": elem.price}
}
})
})
console.log(items)

filter result using 2 JSON

This is my saved localstorage,
[{"industry_Id":1,"merchant_id":2}]
I want to filter below result, to get HP.
{
"industries": [
{
"id": 1,
"name": "oil and gas",
"merchant": [
{
"id": 1,
"name": "ABC",
},
{
"id": 2,
"name": "DEF",
},
{
"id": 3,
"name": "GHJ",
}
]
},
{
"id": 2,
"name": "IT",
"merchant": [
{
"id": 1,
"name": "Apple",
},
{
"id": 2,
"name": "HP",
},
{
"id": 3,
"name": "Google",
}
]
}
]
}
I thought of using multiple $.each but it have to iterate few times and it's quite redundant.
I would prefer using Javascript for loop, that way you can skip iterating over every object once required element is found.
Without jQuery (using for)
var i, j, merchant = null;
for(i = 0; i < data['industries'].length; i++){
if(data['industries'][i]['id'] == arg[0]['industry_Id']){
for(j = 0; j < data['industries'][i]['merchant'].length; j++){
if(data['industries'][i]['merchant'][j]['id'] == arg[0]['merchant_id']){
merchant = data['industries'][i]['merchant'][j];
break;
}
}
if(merchant !== null){ break; }
}
}
With jQuery (using $.each)
var merchant_found = null;
$.each(data['industries'], function(i, industry){
if(industry['id'] == arg[0]['industry_Id']){
$.each(industry['merchant'], function(i, merchant){
if(merchant['id'] == arg[0]['merchant_id']){
merchant_found = merchant;
}
return (!merchant_found);
});
}
return (!merchant_found);
});
var arg = [{"industry_Id":1,"merchant_id":2}];
var data = {
"industries": [
{
"id": 1,
"name": "oil and gas",
"merchant": [
{
"id": 1,
"name": "ABC",
},
{
"id": 2,
"name": "DEF",
},
{
"id": 3,
"name": "GHJ",
}
]
},
{
"id": 2,
"name": "IT",
"merchant": [
{
"id": 1,
"name": "Apple",
},
{
"id": 2,
"name": "HP",
},
{
"id": 3,
"name": "Google",
}
]
}
]
};
var i, j, merchant = null;
for(i = 0; i < data['industries'].length; i++){
if(data['industries'][i]['id'] == arg[0]['industry_Id']){
for(j = 0; j < data['industries'][i]['merchant'].length; j++){
if(data['industries'][i]['merchant'][j]['id'] == arg[0]['merchant_id']){
merchant = data['industries'][i]['merchant'][j];
break;
}
}
if(merchant !== null){ break; }
}
}
console.log(merchant);
document.writeln("<b>Without jQuery:</b><br>");
document.writeln((merchant !== null) ? "Found " + merchant['name'] : "Not found");
var merchant_found = null;
$.each(data['industries'], function(i, industry){
if(industry['id'] == arg[0]['industry_Id']){
$.each(industry['merchant'], function(i, merchant){
if(merchant['id'] == arg[0]['merchant_id']){
merchant_found = merchant;
}
return (!merchant_found);
});
}
return (!merchant_found);
});
console.log(merchant_found);
document.writeln("<br><br><b>With jQuery:</b><br>");
document.writeln((merchant_found) ? "Found " + merchant_found['name'] : "Not found");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
selectors.map(function(selector) {
return data.industries.filter(function(industry) {
return industry.id == selector.industry_Id;
})[0].merchant.filter(function(merchant) {
return merchant.id == selector.merchant_id;
})[0].name;
});
// => DEF
If you want "HP", you want industry 2, not industry 1.
.filter(...)[0] is not really optimal. You could use .find(...), but that is not yet universally supported. Or you could use plain old JavaScript and write for loops instead to make it fast. Or you could use objects with ID keys instead of arrays to make lookups faster.
When it comes into a position where collection of data is what you're processing, I suggest you to take a look at underscore.js. It's not optimal choice for the best performance but it does make you code more readable and makes more sense especially when compared with loop.
Say data is a variable which stores your JSON data.
Try this:
// Given this selector criteria
var select = [{"industry_Id":1,"merchant_id":2}];
function filterByCriteria(criteria, data){
var match = [];
_.each(criteria, function(crit){
function matchIndustry(rec){ return rec.id===crit.industry_Id }
function matchMerchant(rec){ return rec.id===crit.merchant_id }
// Filter by industry id
var industry = _.first(_.where(data.industry, matchIndustry));
// Filter by merchant id
var merchant = _.where(industry.merchant, matchMerchant);
_.each(merchant, function addToMatchResult(m){
match.push(m.name);
});
});
return match;
}
var filteredData = filterByCriteria(select, data);
From snippet above, any merchants which match the search criteria will be taken to the match list. Is it more readable to you?
Do you even need numerical id's? Gets super easy when you don't.
/*
{
"industry": {
"oil and gas":{
"merchant": {
"ABC": {
"name": "ABC oil"
},
"DEF": {
"name": "DEF gas"
},
"GHJ" :{
"name": "GHJ oil and gas"
}
}
},
"IT": {
"merchant": {
"Apple" : {
"name": "Apple computers"
},
"HP": {
"name": "Hewlett Packard"
},
"Google": {
"name": "Google. Maw haw haw"
}
}
}
}
}
*/
var data = '{"industry": {"oil and gas":{"merchant": {"ABC": {"name": "ABC oil"},"DEF": {"name": "DEF gas"},"GHJ" :{"name": "GHJ oil and gas"}}},"IT": {"merchant": {"Apple" : {"name": "Apple computers"},"HP": {"name": "Hewlett Packard"},"Google": {"name": "Google. Maw haw haw"}}}}}';
data = JSON.parse(data);
var merchant = data.industry['IT'].merchant['HP'];
alert(merchant.name);
//console.log(merchant.name);

reset object order javascript

I have a object like this
{
"items":{
"2":{
"id":122,
"product_id":"DE",
"price":"9.35",
},
"4":{
"id":15,
"product_id":"CH",
"price":"8.00",
}
"7":{
"id":78,
"product_id":"CH",
"price":"3.00",
}
},
"total_price":"20.35",
"item_count":2,
"unit":"CHF"
}
Do you know how i reset the items order.
now 2, 4, 7
should be 0, 1, 2
Created a JSfiddle that shows you a way.
Im using a custom format function:
function format(object) {
var items = {};
var i = 0;
for (var index in object.items) {
items[i] = object.items[index];
i++;
}
object.items = items;
}
The resulted object is this:
{
"items": {
"0": {
"id": 122,
"product_id": "DE",
"price": "9.35"
},
"1": {
"id": 15,
"product_id": "CH",
"price": "8.00"
},
"2": {
"id": 78,
"product_id": "CH",
"price": "3.00"
}
},
"total_price": "20.35",
"item_count": 2,
"unit": "CHF"
}
How about this
var obj = {
"items":{
"2":{
"id":122,
"product_id":"DE",
"price":"9.35",
},
"4":{
"id":15,
"product_id":"CH",
"price":"8.00",
},
"7":{
"id":78,
"product_id":"CH",
"price":"3.00",
}
},
"total_price":"20.35",
"item_count":2,
"unit":"CHF"
}
var keys = Object.keys(obj.items)
for (var i = 0; i < keys.length; i++) {
obj.items[i] = obj.items[keys[i]];
delete obj.items[keys[i]];
};
console.log(obj);
Object properties do not have order. I assume you want to re-name the properties, counting up from 0, but have the properties maintain the original relative ordering of their keys. (So the property with the smallest name is renamed to 0, the second-to-smallest is 1, etc.)
To do this, get all the property names, and sort the names numerically. Then, get all the values in the same over as their sorted property names. Finally, re-insert those property values with their new property names.
var itemsObj = obj["items"];
// get all names
var propertyNames = Object.keys(itemsObj);
// sort property names in numeric order: ["2", "4", "7"]
propertyNames.sort(function(a,b){ return a-b; });
// get property values, sorted by their property names
// ["2", "4", "7"] becomes [{ "id":122, .. }, { "id":15, ... }, { "id":78, ... }]
var values = propertyNames.map(function(propName) { return itemsObj[propName]; }
// clear out old property and add new property
for(var i=0; i<values.length; ++i) {
delete itemsObj[propertyNames[i]];
itemsObj[i] = values[i];
}
var data = {
"items": {
"2": {
"id": 122,
"product_id": "DE",
"price": "9.35",
},
"4": {
"id": 15,
"product_id": "CH",
"price": "8.00",
},
"7": {
"id": 78,
"product_id": "CH",
"price": "3.00",
}
},
"total_price": "20.35",
"item_count": 2,
"unit": "CHF"
};
var indices = Object.keys(data.items).map(function(i) { return parseInt(i, 10); }),
counter = 0;
indices.sort();
indices.forEach(function (i) {
if (i > counter) { // put here some more collision detecting!
data.items[counter] = data.items[i];
delete data.items[i];
counter++;
}
});
Object properties order is not guaranteed anyway. You should use an array instead.
Take a look at this answer

How to print matched and not matched based on matched condtion using angular?

{
"_id": {
"$oid": "5705f793e4b0acd6e2456804a"
},
"Categories": [
{
"mainmodels": [
{
"submodels": [
{
"price": "2000",
"submodelname": "lumia021",
"Remainingphones": "2",
"Bookedphones": "8",
"Numofphones": "10"
},
{
"price": "4000",
"submodelname": "lumia K6",
"Remainingphones": "0",
"Bookedphones": "15",
"Numofphones": "15"
}
],
"Status": "Active",
"modelname": "lumia",
"fromdate": "2016-04-01T16:39:12.051Z",
"todate": "2016-04-31T19:19:44.051Z"
}
],
"brand": "nokia"
}
],
"rank": "1",
"name": "kalasipalaya"
}
I have given my object above i need to check every submodel(here two sumodels is there)Numofphones and Bookedphones are matched . if both(here i given two submodel) Numofphones and Bookedphones are matched i need to print matched otherwise i need to print not matched how can i solve this one help me out .
//This will take to submodel array of object
var _getSubModel = m[0].Categories[0].mainmodels[0].submodels;
var _newArray2 = [];
//Checking if Bookedphones of first object submodel, is same with other objects.
var _newArray = _getSubModel.filter(function(item){
return item.Bookedphones == _getSubModel[0].Bookedphones;
})
// If all the Bookedphones are same then length of _newArray & submodel will be same.
// If same then check for Numofphones
if(_getSubModel.length == _newArray.length){
_newArray2 = _getSubModel.filter(function(item){
return item.Numofphones == _getSubModel[0].Numofphones;
})
// If all Numofphones are same,then length of _newArray2 & submodel will be same
if(_getSubModel.length == _newArray2.length){
console.log('Matched');
}
else{
console.log('Not Matched');
}
}
else{
console.log('Not Matched');
}
Check this jsfiddle
You can use custom filter something like that:
var result = [];
angular.forEach(submodels, function (submodel) {
if(submodel.Numofphones == submodel.Bookedphones)
result.push(submodel);
});
return result;
http://jsfiddle.net/y7r1xe0t/236/
UPDATED: http://jsfiddle.net/y7r1xe0t/237/
return function (submodels, matched_or_not) {
var result = [];
angular.forEach(submodels, function (submodel) {
if(matched_or_not && submodel.Numofphones == submodel.Bookedphones)
result.push(submodel);
else if(!matched_or_not && submodel.Numofphones != submodel.Bookedphones)
result.push(submodel);
});
return result;
};
Filter will return matched object when you send true.

Categories

Resources