Assign circular array to object - javascript

I'm a fresher to java-script. I created a object and with key value pairs. Newly I need to add another key (color) with value which should be from color array (color[]). If the object size is greater than color array size, then the value for the color key should be assigned from beginning of color array
var sumArray=[{"sum":1},{"sum":2},{"sum":3},{"sum":4},{"sum":5},{"sum":6}]
var color=["#FF0F00","#FF6600","#FF9E01"];
var combinedObj =sumArray.map(function(obj) {
var me = Object.assign({}, obj);
var i=0;
me.color = color[i++];
return me;
});
Output is
[{"sum":1,"color":"#FF0F00"},{"sum":2,"color":"#FF0F00"},
{"sum":3,"color":"#FF0F00"},{"sum":4,"color":"#FF0F00"},
{"sum":5,"color":"#FF0F00"},{"sum":6,"color":"#FF0F00"}]
Expected Output is
[{"sum":1,"color":"#FF0F00"},{"sum":2,"color":"#FF6600"},
{"sum":3,"color":"#FF9E01"},{"sum":4,"color":"#FF0F00"},
{"sum":5,"color":"#FF6600"},{"sum":6,"color":"#FF9E01"}]
The value is circulating from the beginning if the object size is greater than color array size.
I tried my best by referring. But failed. Thanks in advance

You want to define the iterator outside the loop, and reset it to zero, when it gets to the smallest arrays length
var sumArray = [{"sum": 1}, {"sum": 2}, {"sum": 3}, {"sum": 4}, {"sum": 5}, {"sum": 6}]
var color = ["#FF0F00", "#FF6600", "#FF9E01"];
var i = 0;
var combinedObj = sumArray.map(function(obj) {
var me = Object.assign({}, obj);
i = i === color.length ? 0 : i;
me.color = color[i++];
return me;
});
console.log( JSON.stringify( combinedObj, 0, 4 ) )
You could just reduce the array instead
var sumArray = [{"sum":1},{"sum":2},{"sum":3},{"sum":4},{"sum":5},{"sum":6}]
var color = ["#FF0F00","#FF6600","#FF9E01"];
var combinedObj = sumArray.reduce( (a,b,i) =>
(a.push(Object.assign({}, b, {color:color[i%color.length]})), a)
, []);
console.log( JSON.stringify(combinedObj, 0, 4) )

Your issue is in this line:
var i=0;
move it out of the loop, and in the loop the increment must be:
i = (i + 1) % color.length;
var sumArray=[{"sum":1},{"sum":2},{"sum":3},{"sum":4},{"sum":5},{"sum":6}]
var color=["#FF0F00","#FF6600","#FF9E01"];
var i=0;
var combinedObj = sumArray.map(function(obj) {
var me = Object.assign({}, obj);
me.color = color[i];
i = (i + 1) % color.length;
return me;
});
console.log(combinedObj);
A different approach, avoiding global variables, can be based on second map parameter:
var sumArray=[{"sum":1},{"sum":2},{"sum":3},{"sum":4},{"sum":5},{"sum":6}]
var color=["#FF0F00","#FF6600","#FF9E01"];
var combinedObj = sumArray.map(function(obj, idx) {
var me = Object.assign({}, obj);
me.color = color[idx % color.length];
return me;
});
console.log(combinedObj);

Just check if i value is 3, then assign it back to 0
var sumArray = [{
"sum": 1
}, {
"sum": 2
}, {
"sum": 3
}, {
"sum": 4
}, {
"sum": 5
}, {
"sum": 6
}]
var color = ["#FF0F00", "#FF6600", "#FF9E01"];
var i = 0;
var combinedObj = sumArray.map(function(obj) {
obj.color = color[i];
i++;
if (i === 3) {
i = 0;
}
return obj
}, {});
console.log(combinedObj)

Related

How to decrement items in array Incrementally based on the given quantity in Javascript

I have this sample array of objects
mangoes:[
{ quantity:5},
{ quantity:8},
{ quantity:13},
{ quantity:4}
]
When I remove x mangoes, that x should be subtracted from the first element in the array, and if that x exceed the first element then it should reduce the remained quantity in the second item in the array...and so forth.
This is to say, I need the quantity to be reduced starting from the first one in the array down to the second if it exceed, to the third etc..
For example, If I buy 2 mangoes, It should minus 2 in the first array element and the resulting mangoes array should be
mangoes:[
{ quantity:3},
{ quantity:8},
{ quantity:13},
{ quantity:4}
]
On the other hand, If I would have bought 7 mangoes, it should reduce all 5 from first array element and then remove 2 mangoes from the second element...and hence the final array would be like this below
mangoes:[
{ quantity:0},
{ quantity:6},
{ quantity:13},
{ quantity:4}
]
By Using Javascript, how can I achieve this?
WHAT I HAVE TRIED
I have tried like this below, It works only for the first element(case) when the x is less, but for other case it doesn't work;
var x = 2
var done = false
mangoes.forEach(function (item,i) {
if(mangoes[i].quantity>=x && !done){
item.quantity = mangoes[i].quantity - x
done = true
}
})
const takeMangoes = (num, from) => from.map(x => {
const take = Math.min(x.quantity, num);
num -= take;
// Original way, keep all properties, don't mutate original
//return {...x, quantity: x.quantity - take};
// Pick from below:
// New way 1, mutate original in place
x.quantity = x.quantity - take;
return x;
// New way 2, limit to OWN properties
return Object.getOwnPropertyNames(x).reduce((a, c) => {
a[c] = x[c];
if (c === 'quantity') {
a[c] -= take;
}
return a;
}, {});
}).filter(x => x.quantity > 0);
console.log(takeMangoes(2, [
{quantity: 5},
{quantity: 8},
{quantity: 13},
{quantity: 4},
]));
console.log('------------------------');
console.log(takeMangoes(7, [
{quantity: 5},
{quantity: 8},
{quantity: 13},
{quantity: 4},
]));
You can take a closure inside map and generate the desired result.
var mangoes=[ { quantity:5},{ quantity:8},{ quantity:13},{ quantity:4}];
var toReduce = 5;
var result = mangoes.map((num=>({quantity})=>(r = Math.min(quantity,num),num=num-r,({quantity:quantity-r})))(toReduce));
console.log(result);
You can achieve that with forEach this way. But I wouldn't recommend it because even if a quantity is found to be greater than the value to be deducted, it will still loop through the whole item list as you can't break out of a forEach loop
var mangoes = [
{ quantity:0},
{ quantity:6},
{ quantity:13},
{ quantity:4}
];
var x = 2
var done = false
mangoes.forEach(function (item,i) {
if(item.quantity< x){
item.quantity = 0;
x = x- item.quantity;
}else{
item.quantity = item.quantity-x;
x=0;
}
});
console.log(mangoes)
However, I would recommend using for..of..loop so that you could conditionally break out of the loop, i.e if the quantity is found to be greater than the ones to be deducted, just deduct and break out of the loop. There's no need of further iteration.
var mangoes = [
{ quantity:5},
{ quantity:6},
{ quantity:13},
{ quantity:4}
];
var x = 1
var done = false
for(let i of mangoes){
if(i.quantity >= x){
i.quantity = i.quantity -x;
x = x - i.quantity;
break;
}else{
x = x - i.quantity;
i.quantity = 0;
}
}
console.log(mangoes)
let x = 8;
const newMangoes = mangoes.map((mango) => {
if (!x) return mango;
if (x <= mango.quantity) {
newMango = {quantity: mango.quantity - x};
x = 0;
return newMango;
} else {
x = x - mango.quantity;
return {quantity: 0};
}
});
var getMangoes = function(requested){
var remaining = requested;
var supplied = 0;
for(var i = 0; i < mangoes.length() && supplied < requested; i++){
if(mangoes[i].quantity >= remaining){
mangoes[i].quantity -= remaining;
supplied += remaining;
}
else {
remaining -= mangoes[i].quantity;
supplied += mangoes[i].quantity;
}
}
return(supplied);
};
var mangoesIWant = 13;
var mangoesIGot = getMangoes(mangoesIWant);

Calculate percentage from associative array in JS

Suppose I have an array like this:
var arr = [];
arr["india"] = 7;
arr["indonesia"] = 3;
arr["usa"] = 1;
[india: 7, indonesia: 3, usa: 1]
I need to get an array like [india: (7/11*100), indonesia: (3/11*100), usa: (1/11*100)] , i.e., to get the percentage of each country value using a single loop in javascript. How can I achieve it ?
You can use array#reduce to sum up all values and then calculate percentages inside array#map
var arr = {};
arr["india"] = 7;
arr["indonesia"] = 3;
arr["usa"] = 1;
let sum = Object.keys(arr).reduce((s,k) => s += arr[k], 0);
var result = Object.keys(arr).map(k => ({[k] : (arr[k]/sum * 100).toFixed(2)}));
console.log(result);
If your objects is like this var arr = {india: 7, indonesia: 3, usa: 1};, you can do it in this way.
var arr = {india: 7, indonesia: 3, usa: 1};
var sum = 0;
//Finding the sum
for(key in arr){
sum += arr[key];
}
console.log("Sum of the object values is = " + sum);
//Finding the average
for(key in arr){
arr[key] = (arr[key]/sum)*100;
}
console.log(arr);
Loop through each key and reassigned the val like this:
var countries = [];
countries["india"] = 7;
countries["indonesia"] = 3;
countries["usa"] = 1;
for (var country in countries){
if (countries.hasOwnProperty(country)) {
countries[country] = (countries[country] / 11 * 100).toFixed(2)
}
}
console.log(countries)
[india: 7, indonesia: 3, usa: 1]is wrong, you need an object, like {india: 7, indonesia: 3, usa: 1}
So, I think you need an function to do what you need, simple:
var obj = {india: 7, indonesia: 3, usa: 1}
const getPercent = (obj) {
let sum = 0
for (key in obj) {
sum += obj[key]
}
for (key in obj) {
obj[key] = (obj[key]/sum)*100
}
return obj
}
Once you change the obj, you run getPercent(obj), then you get a return, that is what's you need.
May helpful.
So, suppose you have a valid array:
var myArray = { 'key1': 2, 'key2': 5, 'key3': 14 };
/* iterates through an associative array, calculates each percentage and
adds it to a similar associative array
The percentages are not rounded
*/
function getPercentagePerKey(myArray) {
var sum = getSum(myArray);
var arrayWithPercentages = [];
for (key in myArray) {
val = myArray[key];
percentage = (val / sum) * 100;
arrayWithPercentages.push({key, percentage});
}
return arrayWithPercentages;
}
/* returns the sum given from an 'associative' array */
function getSum(myArray) {
var sum = 0;
for (key in myArray) {
sum += myArray[key];
}
return sum;
}
percentageArray = getPercentagePerKey(myArray);
console.log(percentageArray);
0: {key: "key1", percentage: 9.523809523809524}
1: {key: "key2", percentage: 23.809523809523807}
2: {key: "key3", percentage: 66.66666666666666}
You can make getters from object properties if it is allowed:
var arr = {};
arr["india"] = 7;
arr["indonesia"] = 3;
arr["usa"] = 1;
var sum = 0;
var percent = function(n){
return function(){ return n/sum*100; }
}
for (var k in arr) {
sum+=arr[k];
arr[k]=percent(arr[k]);
}
console.log(arr.india());
console.log(arr.usa());
console.log(arr.indonesia());

how to create json with two array in javascript

I have two json:
I want to create json with those two array;
var __columns = ["Field1", "Field2", "Field3", "Field4"];
var __rows = ["valueField1_1", "valueField2_1", "valueField3_1", "valueField4_1", "valueField1_2", "valueField2_2", "valueField3_2", "valueField4_2", "valueField1_3", "valueField2_3", "valueField3_3", "valueField4_3"];
The thing is that I wanna create something like this
var json = [{
"Field1":"valueField1_1",
"Field2":"valueField2_1",
"Field3":"valueField3_1",
"Field4":"valueField4_1"
},{
"Field1":"valueField1_2",
"Field2":"valueField2_2",
"Field3":"valueField3_2",
"Field4":"valueField4_2"
},{
"Field1":"valueField1_3",
"Field2":"valueField2_3",
"Field3":"valueField3_3",
"Field4":"valueField4_3"
}]
ES6 solution using Array.from and Array#reduce methods.
var __columns = ["Field1", "Field2", "Field3", "Field4"];
var __rows = ["valueField1_1", "valueField2_1", "valueField3_1", "valueField4_1", "valueField1_2", "valueField2_2", "valueField3_2", "valueField4_2", "valueField1_3", "valueField2_3", "valueField3_3", "valueField4_3"];
var res = Array.from({
// generate array with particular size
length: __rows.length / __columns.length
// use map function to generate array element
}, (_, i) => __columns.reduce((obj, e, i1) => {
// define object property based on the index values
obj[e] = __rows[i * __columns.length + i1];
return obj;
// set empty object as initial argument
}, {}));
console.log(res);
function convertToJsonArr(__columns, __rows){
var obj = {};
var arr = [];
var len = __columns.length;
var count = 0;
$.each(__rows , function(key, value){
if(count >= len){
count = 0;
arr.push(obj);
obj = {};
}
obj[__columns[count++]] = value;
})
arr.push(obj);
return arr;
}
you can call like convertToJsonArr(__columns, __rows);
One way to achieve this is using loops
var __columns = ["Field1", "Field2", "Field3", "Field4"];
var __rows = ["valueField1_1", "valueField2_1", "valueField3_1", "valueField4_1", "valueField1_2", "valueField2_2", "valueField3_2", "valueField4_2", "valueField1_3", "valueField2_3", "valueField3_3", "valueField4_3"];
var arr = [];
for(var i = 0; i < __rows.length; i = i + __columns.length){
var tempObj = {};
for(var j = 0; j < __columns.length; ++j){
tempObj[__columns[j]] = __rows[i];
}
arr.push(tempObj);
}
console.log(arr);

Remove JSON entry by value [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Delete from array in javascript
I have the following JSON object:
[id:84,id:92,id:123,id:2353]
How would I go about removing the item which the value is "123" using javascript?
or if I formatted the json as
[84, 92, 123, 2353]
How would it be removed in this case?
Assume you have this:
var items = [{ id: 84 }, { id: 92 }, { id: 123 }, { id: 2353 }];
var filtered = items.filter(function(item) {
return item.id !== 123;
});
//filtered => [{ id: 84 }, { id: 92 }, { id: 2353 }]
Supposing you actually have an object from a json in the json variable
for (key in json) {
if (json.hasOwnProperty(key) && json[key] == 123) {
delete json[key];
}
}
Shorter alternative would be:
var newArr = [{id:84}, {id:92}, {id:123}, {id:2353}].filter(function(a) {
return a.id != 123;
});
If you have this:
var arr = [{id:84}, {id:92}, {id:123}, {id:2353}]
To remove the item with value 123, you can do:
for(var i = 0; i < arr.length; i++) {
if(arr[i].id == 123) {
arr.splice(i, 1);
break;
}
}
function removeClass(obj, cls) {
var classes = obj.className.split(' ');
for(i=0; i<classes.length; i++) {
if (classes[i] == cls) {
classes.splice(i, 1);
i--; // (*)
}
}
obj.className = classes.join(' ');
}
var obj = { className: 'open menu menu' }
removeClass(obj, 'menu')
alert(obj.className)
You can use splice function, like this:
var data = [{id:84}, {id:92}, {id:123}, {id:2353}];
function remove(){
for(var i = 0, max = data.length; i < max; i++) {
var a = data[i];
if(a.id === 123) {
data.splice(i, 1);
break;
}
}
}
remove();
Seems like you want to avoid a loop. Assuming it's available, you can use .filter:
[{id:84},{id:92},{id:123},{id:2353}]
.filter(function (elem) { return elem.id !== 123; });
This technically does do a loop, but at least you don't have to look at it.
Assuming your "json" is really an array, like [84, 92, 123, 2353]:
var myString = "[84, 92, 123, 2353]";
var myArray = JSON.parse(myString);
var index = myArray.indexOf(123); // whatever value you are looking for
myArray.splice(index, 1);
http://jsfiddle.net/7vkK6/
Assuming I'm understanding your question and comments correctly you can do something like this:
var old_array = [{id: 84},...];
var new_array = [];
for(var i = 0, len = old_array.length; i++) {
if (old_array[i].id != 123) new_array.push(old_array[i]);
}
What you have currently is not JSON so I'll give you some different options.
If you have an Array arr = [84,92,123,2353] then
arr = arr.filter(function (x) {return x !== 123;}); // all occurrences
// OR
arr.splice(arr.indexOf(123), 1); // first occurrence only
If you have an Object obj = {"84": a, "92": b, "123": c, "2353": d}, a to d some expressions, then
delete obj['123']; // obj now {"84": a, "92": b, "2353": d}
1) JSON is a string, not an array or an object.
var json = "[1,2,3]";
2) Valid JSON NEEDS to be valid JS
var myJSObj = { 1,2,3 }, // broken
myJSArr = [ name : 1, name2 : 2 ]; // broken
3) If you have a JS Array, you can remove an element by using [].splice
var arr = [ 1, 2, 3, 4 ],
i = 0, l = arr.length,
test = 4;
for (; i < l; i += 1) {
if (arr[i] === test) { arr.splice(i, 1); } // remove 1 starting at i
}
4) If you have an object with named keys, you can use delete
var obj = { val : 1 };
delete obj.val;

How to $.extend 2 objects by adding numerical values together from keys with the same name?

I currently have 2 obj and using the jquery extend function, however it's overriding value from keys with the same name. How can I add the values together instead?
var obj1 = {
"orange": 2,
"apple": 1,
"grape": 1
};
var obj2 = {
"orange": 5,
"apple": 1,
"banana": 1
};
mergedObj = $.extend({}, obj1, obj2);
var printObj = typeof JSON != "undefined" ? JSON.stringify : function (obj) {
var arr = [];
$.each(obj, function (key, val) {
var next = key + ": ";
next += $.isPlainObject(val) ? printObj(val) : val;
arr.push(next);
});
return "{ " + arr.join(", ") + " }";
};
console.log('all together: ' + printObj(mergedObj));
And I get obj1 = {"orange":5,"apple":1, "grape":1, "banana":1}
What I need is obj1 = {"orange":7,"apple":2, "grape":1, "banana":1}
All $.extend does is join the two objects but it doesn't add the values, it overrides them.
You're going to have to do this manually. $.extend will be useful to add or modify fruits to your object but if you need the total sum you gonna have to loop:
var obj1 = { orange: 2, apple: 1, grape: 1 };
var obj2 = { orange: 5, apple: 1, banana: 1 };
var result = $.extend({}, obj1, obj2);
for (var o in result) {
result[o] = (obj1[o] || 0) + (obj2[o] || 0);
}
console.log(result); //=> { orange: 7, apple: 2, grape: 1, banana: 1 }
Demo: http://jsfiddle.net/elclanrs/emGyb/
Working Demo
That's not how .extend() works; you'll have to implement your own:
function mergeObjects() {
var mergedObj = arguments[0] || {};
for (var i = 1; i < arguments.length; i++) {
var obj = arguments[i];
for (var key in obj) {
if( obj.hasOwnProperty(key) ) {
if( mergedObj[key] ) {
mergedObj[key] += obj[key];
}
else {
mergedObj[key] = obj[key];
}
}
}
}
return mergedObj;
}
Usage:
var obj1 = { "orange": 2, "apple": 1, "grape": 1 };
var obj2 = { "orange": 5, "apple": 1, "banana": 1 };
var mergedObj = mergeObjects( obj1, obj2);
// mergedObj {"orange":7,"apple":2,"grape":1,"banana":1}
Of course, like .extend(), this will work with any number of objects -- not just 2.
No fancy stuff, just simple Javascript:
The c[k] || 0 is there in the event that c[k] has no value, it gets to be zero.
var a = {orange:2, apple:1, grape:1};
var b = {orange:5, apple:1, banana:1};
var c = {};
var k;
for (k in a) {c[k] = 0 + a[k] + (c[k] || 0)}
for (k in b) {c[k] = 0 + b[k] + (c[k] || 0)}
window.alert(JSON.stringify(c));
Here's some code you could use:
obj1 = {"orange":2,"apple":1, "grape":1};
obj2 = {"orange":5,"apple":1, "banana":1};
var joined = {};
// add numbers in arr to joined
function addItems(arr) {
// cycle through the keys in the array
for (var x in arr) {
// get the existing value or create it as zero, then add the new value
joined[x] = (joined[x] || 0) + arr[x];
}
}
addItems(obj1);
addItems(obj2);
console.log(JSON.stringify(joined));
Output:
{"orange":7,"apple":2,"grape":1,"banana":1}

Categories

Resources