How to insert values into 2d array at specific index using jQuery - javascript

I have the following 2 arrays:
groupedObjects: [
{ value: 125, currency: "EUR" },
{ value: 100, currency: "USD" },
{value: 320, currency: "RON" }
]
groupedObjects1: [
{ value: 500, currency: "EUR" },
{ value: 280, currency: "RON" }
]
How can I have those 2 arrays look identical?
I would like that second array, after code looked like:
[
{ value: 500, currency: "EUR" },
{ value: 0, currency: "USD" },
{ value: 280, currency: "RON" }
]
I have tried this code:
if ($(groupedObjects).length > $(groupedObjects1).length) {
_.each(groupedObjects,function(obj){
i++;
_.each(groupedObjects1,function(obj1){
if(obj.currency != obj1.currency) {
alert('Test');
groupedObjects1.push ({
value: '',
currency: ''
});
}
});
});
}
I want that both arrays would be sorted by currency and both of them should have same number of elements, no matter wich array would be larger

groupedObjects= [
{ value: 125, currency: "EUR" },
{ value: 100, currency: "USD" },
{value: 320, currency: "RON" }
];
groupedObjects1= [
{ value: 500, currency: "EUR" },
{ value: 280, currency: "RON" }
];
if ($(groupedObjects).length > $(groupedObjects1).length) {
var newArray = [];
$.each(groupedObjects, function (key, value) {
var flag = false;
var breakout = false;
flag = (function () {
$.each(groupedObjects1, function (key1, value1) {
if (value.currency === value1.currency) {
newArray.push(value1);
breakout = true;
return false;
}
});
if (!breakout) {
return true;
}
})();
if (flag) {
newArray.push({
value: 0,
currency: value.currency
});
}
});
groupedObjects1 = newArray;
}

Well, there are a couple of ways to approach this, and hacking together a function that adds blank values into an array is certainly one of them, but a more object-oriented approach is going to help you a lot more.
I'm not sure how "advanced" you are with javascript, so I'm sorry if it sounds like I'm babying you.
The first thing we want to do is set up a Currency class. There are a few ways to do this, but I prefer the one below, most likely because I'm from a C++ background. Feel free to use another method if you wish.
function Currency(type, quantity){
this.type = type;
this.quantity = quantity;
}
If you want, you could add some validation, such as making sure that quantity is greater than 0 or that type is a valid currency. You could also make those properties private and implement accessors for them, but I'm just trying to keep it simple for now. If you'd like, you could extend it for each currency, so you could say new USD(280) to create a USD object with a value of 280.
So, now that we have our currencies settled, we can think about how we want to store them. We want to make sure that if we haven't added a currency, its quantity is equal to 0. To do this, we'll instantiate an object for each type of currency, then set its value as necessary.
Here's a really simple implementation:
function CurrencyList(){
var valid_currencies = ["EUR", "RON", "USD"];
this.currencies = [];
for(i in valid_currencies){
this.currencies[i] = new Currency(valid_currencies[i], 0);
}
}
I just created an array of valid currencies, iterate through them, and create a "public" property with the valid currency object. I store it in an array like in you have already, it's just in an object.
We're not done yet, though. What if some nefarious person deleted an element in our array? We'd be back to your original problem. We can solve this by making currencies invisible outside the object.
function CurrencyList(){
var valid_currencies = ["EUR", "RON", "USD"];
currencies = [];
for(i in valid_currencies){
currencies[i] = new Currency(valid_currencies[i], 0);
}
}
Now if we try something like this:
var currency_list = new CurrencyList();
alert(currency_list.currencies[0]);
We get an error, which means that our array cannot be modified from outside.
This introduces another problem: what if we want to view an element in our array? The answer is to implement an accessor (a "get") method.
All we have to is create a "public" property and set it equal to a function, like this:
this.at = function(index){
return currencies[index];
}
Now we can access a currency like this:
var currency_list = new CurrencyList();
alert(currency_list.at(0));
This is it all put together:
function CurrencyList(){
var valid_currencies = ["EUR", "RON", "USD"];
currencies = [];
for(i in valid_currencies){
currencies[i] = new Currency(valid_currencies[i], 0);
}
this.at = function(index){
return currencies[index];
}
}
function Currency(type, quantity){
this.type = type;
this.quantity = quantity;
}
This will ensure that you can't have mismatched arrays, so we don't have to bother with a hacky, post hoc solution. In other words, it doesn't solve your problem, but rather prevents the problem from ever existing, which is an even better solution. It also ensures that your array is sorted by currency, because the elements will always be in the order that you specify in your constructor.

Don't use push() Insert de item in the same index.
Use that:
if ($(groupedObjects).length > $(groupedObjects1).length) {
_.each(groupedObjects,function(obj){
i++;
_.each(groupedObjects1,function(index, obj1){
if(obj.currency != obj1.currency) {
alert('Test');
groupedObjects1[index] = ({
value: '',
currency: ''
});
}
});
});
}

Related

How to add dynamic elements to an object in typescript

I am sorry if I am asking a very basic question, I have done some research over the internet but not getting anything useful.
I have a typescript object like :
var productIds=["one","two","three"];
let searchfilter = {
or: [{
id: { match:productids['0'] }
},{
id: { match:productids['1'] }
},{
id: { match:productids['2'] }
}]
};
My productIds can be dynamic and may hold different counts of values.
How can I create the same structure for a dynamic number of values. I tried forEach, but not sure about the syntax.
productids.forEach(function(value){
// not sure if this is right syntax, I am not getting desired results.
searchfilter.or = { id: { match:value }};
});
Can you help me with it?
You can create your full or array with a simple .map() :
var productIds = ["1", "2", "3"];
let searchfilter = {
or : productIds.map( n => ({ id : { match : productIds[n] } }))
};
However Mongo (which I believe you are using) has a $match method that's made to match a list :
{
$match: {
productIds: {
$in: productIds
}
}
}
I'll keep it as simple as I can
var productIds=["one","two","three"];
let searchfilter = productIds.map(p => {
return {id: { match: p }};
});
// function
addNewProduct(id: string) {
this.searchfilter.push({id: { match: id }});
}

i wanna return correctly children's object. how can i?

function Ha8(arr, id) {
let result = [];
for(let i = 0; i < arr.length; i++) {
if(Array.isArray(arr[i].children)) {
// if it is a array, it going to be run recursive
result.push(arr[i].children)
const col = Ha8(result[i], id);
if(col === id) {
// find it in array in array
return result
// then return the id object,
} else {
continue; // still can't find.. go ahead!
}
} else if (arr[i]['id']===id) {
return arr[i] // will return valid id object
}
return null // if its none , return null, or parameter id is undefined.
}
}
I m write Intended direction. but its not work..
how can i fix ? give me some tip please.
let input = [
{
id: 1,
name: 'johnny',
},
{
id: 2,
name: 'ingi',
children: [
{
id: 3,
name: 'johnson',
},
{
id: 5,
name: 'steve',
children: [
{
id: 6,
name: 'lisa',
},
],
},
{
id: 11,
},
],
},
{
id: '13',
},
];
output = Ha8(input, 5);
console.log(output); // --> { id: 5, name: 'steve', children: [{ id: 6, name: 'lisa' }] }
output = Ha8(input, 99);
console.log(output); // --> null
I wanna return like that, but only return 'null' ..
need to check children's id and return children's object by using recursive.
so i write like that. but i have no idea..
how to return correctly children id's element?
I will give you an answer using a totally different approach, and using the magic of the JSON.stringify() method, more specifically the replacer optional parameter, which allows the use of a callback function that can be used as a filter.
As you can see, it simplifies a lot the final code. It could also be modified to introduce not only an id, but also any key or value, as I did in my final approach.
EDIT: Following your suggestion, as you prefer your function to be recursive, I recommend you to use the Array.reduce() method. It allows an elegant iteration through all the properties until the needs are met.
Using null as initial value, which is the last argument of the reduce method, it allows to iterate through all fields in the array in the following way:
The first if will always be skipped on the first iteration, as the initial value is null.
The second if will set the currentValue to the accumulator if the property id exists and is equal to the value you are trying to find
The third if, which you could add an Array.isArray() to add a type validation, will check if the property children exists. As it is the last one, it will only work if all the other conditions aren't met. If this property exists, it will call again Ha8Recursive in order to start again the process.
Finally, if neither of this works, it should return null. The absence of this last condition would return undefined if the input id doesn't exist
const Ha8 = (array, inputKey, inputValue) => {
let children = null;
JSON.stringify(array, (key, value) => {
if (value[inputKey] && value[inputKey] === inputValue) {
children = value;
}
return value;
});
return children;
};
const Ha8Recursive = (array, inputKey, inputValue) => {
return array.reduce((accumulator, currentValue) => {
if (accumulator) {
return accumulator;
} else if (currentValue[inputKey] && currentValue[inputKey] === inputValue) {
return currentValue;
} else if (currentValue.children) {
return Ha8Recursive(currentValue.children, inputKey, inputValue);
} else {
return null;
}
}, null)
}
const input = [{"id":1,"name":"johnny"},{"id":2,"name":"ingi","children":[{"id":3,"name":"johnson"},{"id":5,"name":"steve","children":[{"id":6,"name":"lisa"}]},{"id":11}]},{"id":"13"}];
console.log('JSON stringify function');
console.log(Ha8(input, 'id', 5));
console.log('Recursive function')
console.log(Ha8Recursive(input, 'id', 5));

Set same function to multiple objects in javascript

I have a list of objects like this
var obj = [
{ name: "user", per: { pu: [{ end: "foo" }], ge: [{ end: "bar" }] } },
{ name: "user2", per: { pu: [{ end: "foo2" }], ge: [{ end: "bar2" }] } }
];
I want to add a new property cond which is a function to the objects in pu and ge, but when i do this, the function set to the only last object.
I loop through them then set them like so obj[0].per[itm][0].cond = func and that set to the last object only, but when i try to convert function toString() it set to all, JSON.stringfy() works as func same behavior.
Have I clone or set it in another way?
You may need to post fuller code as it's difficult to see where your error is. However, considering it from scratch, I think some nested loops to match the nested arrays will get you there.
for (let o of obj) {
for (let puObj of o.per.pu) {
puObj.cond = func;
}
for (let geObj of o.per.ge) {
geObj.cond = func;
}
}
use the below function...
const updateObject = (oldObject, updatedProperties) => {
return {
...oldObject,
...updatedProperties
}
};
then you can pass in your new function or anything you need to add like this:
obj[index].per = updateObject(obj[index].per, {cond : function() {}} ); //use a loop to add the function to all objects in array
//check your current obj
console.log(obj);

vuex filter object in store

I have an object of objects in my Vuex state that I am trying to filter to update the UI. I am having trouble filtering the object by one of the properties in the object. I am trying to avoid creating a temporary object to hold the filtered data.
Here is my data object:
var data = {
'xxxxx' : {
id: 'xxxxx',
assessed_value: 1900,
creditid: 'zzzzz',
full_value: 100,
population: 200
},
'yyyy' : {
id: 'yyyy',
assessed_value: 2000,
creditid: 'pppp',
full_value: 300,
population: 400
},
'aaaa' : {
id: 'aaaa',
assessed_value: 5000,
creditid: 'pppp',
full_value: 100,
population: 600
}
};
I am trying to filter by creditid. For example, I want to retrieve all objects in the state with a creditid === 'pppp'.
I created a function that filters by creditid but it returns an array of objects.
function getCreditId(obj, key, val) {
return Object.values(obj).filter(x => x[key] === val);
}
I would like to filter the state by data[creditid] so that I am not creating another object. But not sure how to bypass the keys for each object ['yyyy', 'aaaa'] when doing the filter. Any suggestions?
One way to solve it is by using the reduce function.
var attribute = 'creditid';
var value = 'pppp';
var keys = Object.keys(data);
var result = keys.reduce(function(a, k) {
if (data[k][attribute] === value) {
a.push(data[k]);
}
return a;
}, []);

Reproducing MongoDB's map/emit functionality in javascript/node.js (without MongoDB)

I like the functionality that MongoDB provides for doing map/reduce tasks, specifically the emit() in the mapper function. How can I reproduce the map behavior shown below in javascript/node.js without MongoDB?
Example (from MongoDB Map-Reduce Docs):
[{ cust_id: "A123", amount: 500 }, { cust_id: "A123", amount: 250 }, { cust_id: "B212", amount: 200 }]
Mapped to -
[{ "A123": [500, 200] }, { "B212": 200 }]
A library that makes it as simple as Mongo's one line emit() would be nice but native functions would do the job as well.
Array.reduce does what you need.
here is documentation: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
I also suggest you to use undescore.js (as in first comment) which has reduce & reduceRight.
http://underscorejs.org/#reduce
If you just neeed to have the emit syntax, it's possible. Scan out the function body and pass in a new emit function.
function mapReduce(docs, m, r) {
var groups = {}
function emit(key, value) {
if (!groups[key]) { groups[key] = [] }
groups[key].push(value)
}
var fn = m.toString()
var body = fn.substring(fn.indexOf('{') + 1, fn.lastIndexOf('}'))
var map = new Function('emit', body)
docs.forEach(function (doc) {
map.call(doc, emit)
})
var outs = []
Object.keys(groups).forEach(function (key) {
outs.push({ _id: key, value: r(key, groups[key]) })
})
return outs
}
Edit, forgot example:
var docs = // from above
Array.sum = function (values) {
return values.reduce(function (a, b) { return a + b })
}
mapReduce(docs,
function () {
emit(this.cust_id, this.amount)
},
function (k, values) {
return Array.sum(values)
}
)
// [ { _id: 'A123', value: 750 }, { _id: 'B212', value: 200 } ]
I agree that there are lots of great lib ways to do this, and it's simple to do with Array methods. Here is a fiddle with my suggestion. It's pretty simple, and just uses the forEach Array method. I've done it in a single loop, but there are many other ways.
I haven't done the reduce at the end, as you didn't ask for that, but I hope this helps.
function emit (key, value, data) {
var res = {}; out = [];
data.forEach(function (item) {
var k = item[key];
var v = item[value];
if (k !== undefined && v !== undefined) {
if (res[k] !== undefined) {
out[res[k]][k].push(v);
} else {
var obj = {};
res[k] = out.length;
obj[k] = [v];
out.push(obj);
}
}
});
return out;
}
var data = [{name: 'Steve', amount: 50},{name: 'Steve', amount: 400}, {name: 'Jim', amount: 400}];
emit('name', 'amount', data)) // returns [{"Steve":[50,400]},{"Jim":[400]}]
emit('amount', 'name', data)) // returns [{"50":["Steve"]},{"400":["Steve","Jim"]}]
I've used an object to store the array index for each unique entry. There are lots of versions of this. Probably many better than mine, but thought I'd give you a vanilla JS version.

Categories

Resources