Nested linq loops - javascript

Iam trying to iterate the below JSON with linq.js , Here my scenario is I am having an array which contains 3,5,6.Based on this array values i need firstName from below JSON. How can i achieve it . The JSON is just given for an example in real time am handling with 50000 records, what is the best way to achieve this?
[
{
"id": "1",
"firstName": "John",
"lastName": "Doe"
},
{
"id": "2",
"firstName": "Anna",
"lastName": "Smith"
},
{
"id": "3",
"firstName": "Peter",
"lastName": "Jones"
},
{
"id": "4",
"firstName": "John",
"lastName": "Doe"
},
{
"id": "5",
"firstName": "Anna",
"lastName": "Smith"
},
{
"id": "6",
"firstName": "Peter",
"lastName": "Jones"
},
{
"id": "7",
"firstName": "John",
"lastName": "Doe"
},
{
"id": "8",
"firstName": "Anna",
"lastName": "Smith"
},
{
"id": "9",
"firstName": "Peter",
"lastName": "Jones"
}
]

Basically what you're trying to do is a join. A naive approach would simply just do a join.
var ids = [ 3, 5, 6 ];
var query = Enumerable.From(data)
.Join(ids, "Number($.id)", "$", "$")
.ToArray();
However this wouldn't work out well when there are many objects to work with since you're performing a linear search for the associated items. You can improve things by creating a lookup of the objects by id. You'll just have to pay the up front cost of creating the lookup.
var lookup = Enumerable.From(data)
.ToObject("Number($.id)");
var ids = [ 3, 5, 6 ];
var query = Enumerable.From(ids)
.Select(function (id) {
return lookup[id];
})
.ToArray();

If you are aware of that big amount of data would hang other process, make the user feel laggy, you can try this:
var process = function(obj, targets, callback, context) {
// Init context
var results = [];
var length = obj.length;
var procLimit = 500; // Whatever the amount you want to process at a time, higher will have higher change to cause lag on browser.
context = context ? context : null;
var current = 0;
// Loop function
var looper = function() {
if (current >= length) {
callback.call(context, result);
return;
}
var end = Math.min(length, current + procLimit);
var id, findIndex;
// Only process a fixed amount of item in a time.
for (; current < end ; ++current) {
id = parseInt(obj[current].id, 10);
findIndex = targets.indexOf(id);
// Find the matched key, and put to result.
if (findIndex >= 0) {
results.push(obj[current]);
// or you just need fname, use
// results.push(obj[current].firstName);
// remove founded from targets
targets.splice(findIndex, 1);
}
}
current += procLimit;
// Non-blocking
setTimeout(looper, 10);
};
// Non-blocking
setTimeout(looper, 10);
};
// Usage
process(YOUR_OBJ, [1, 3, 5, 6], function(processedObj){
// do somthing with the processed Object
}, THE_CONTEXT);
This function will tries to run as in background, and when it complete scan through the json array, it'll call your handler with the founded items in an array as param.
If block-effect is not in concern, then simply use the filter:
var targets = [1, 3, 5, 6];
var filterResult = YOUR_JSON.filter(function(item) {
var id = parseInt(item.id, 10);
return (targets.indexOf(id) >= 0);
}).map(function(item) { return item.firstName; });

Related

Combine javascript objects from an array that contain almost similar key

I have an array that contains objects. The array looks like this:
[
{
"number": "10a",
"person": "Velvet"
},
{
"number": "10b",
"person": "Edna"
},
{
"number": "11a",
"person": "Shionne"
},
{
"number": "11b",
"person": "Aifread"
},
]
I want to combine objects that have identical number property. For example, the first two objects have property number: "10a", and number: "10b". I want these to be combined such that the output becomes:
{
"10": {
"person": ["Velvet", "Edna"]
},
"11": {
"person": ["Shionne", "Aifread"]
}
}
I am not sure how to do it as it seems too complicated for me. I also looked over stackoverflow but can't seem to find a similar problem, hence, my post. Thanks for the help!
I'll assume that the normalization for number is just to remove non numeric characters. If so, you can just iterate over the original array and process each element:
var original = [
{
"number": "10a",
"person": "Velvet"
},
{
"number": "10b",
"person": "Edna"
},
{
"number": "11a",
"person": "Shionne"
},
{
"number": "11b",
"person": "Aifread"
},
];
const merged = {}
original.forEach(item => {
var normalizedKey = item.number.replaceAll( /\D/g, "" )
if(!merged[normalizedKey]) merged[normalizedKey] = { person: []}
merged[normalizedKey].person.push(item.person)
})
console.log({merged})
Parse number. Add object if missing and append name:
const result = {};
arr.forEach(o => {
const nr = o.number.slice(0,2);
result[nr] = result[nr] || {person:[]};
result[nr].person.push(o.person);
});
console.log(result);

JSON data concatenate two data [duplicate]

This question already has an answer here:
How to concatenate two string fields into one in a JavaScript array? [closed]
(1 answer)
Closed 4 months ago.
In Javascript, How can I convert this JSON Data?
I need to concatenate the firstname and lastname into its fullname
Data
[
{
"lastname": "Stark",
"firstname": "Tony",
"id": 1
},
{
"lastname": "Parker",
"firstname": "Peter",
"id": 2
},
{
"lastname": "Rogers",
"firstname": "Steve",
"id": 3
},
]
This should be the result:
Result
[
{
"fullname": "Tony Stark",
"id": 1
},
{
"fullname": "Peter Parker",
"id": 1
},
{
"fullname": "Steve Rogers",
"id": 1
},
]
Use JSON.parse to parse your data into JavaScript object and then with Array#map function iterate over the items and populate your custom objects.
const dataAsJson = `[
{
"lastname": "Stark",
"firstname": "Tony",
"id": 1
},
{
"lastname": "Parker",
"firstname": "Peter",
"id": 2
},
{
"lastname": "Rogers",
"firstname": "Steve",
"id": 3
}
]`;
const data = JSON.parse(dataAsJson);
const changedData = data.map(item => ({ fullname: `${item.firstname} ${item.lastname}`, id: item.id }));
console.log(changedData);
If this data is available to your script as a JSON string, then you can use JSON.parse() to obtain the array of objects.
Then do whatever you want with that array of objects.
Then, eventually, convert the resulting data back to a string using JSON.stringify().
You can also use array#reduce.
const data = `[{"lastname": "Stark","firstname": "Tony","id": 1},{"lastname": "Parker","firstname": "Peter","id": 2},{"lastname": "Rogers","firstname": "Steve","id": 3}]`;
var result = JSON.parse(data).reduce((arr, obj) => {
return arr.push({fullName : obj.firstname + " " + obj.lastname, id: obj.id }), arr;
},[]);
console.log(result);
First, parse the string to get the data in JSON by using
JSON.parse()
. If you're using es6, use this:
const newArray = JSON.parse(yourArray).map((user) => ({
fullName: `${user.firstname} ${user.lastname}`,
id: user.id
}));
otherwise use this:
const newArray = yourArray.map(function (user) {
return {
fullName: user.firstname + user.lastname,
id: user.id
};
});
Thanks.
Logically all you need to do is loop through the array and make a new object with the firstname and lastname contacted. So here is a non-fancy ES5 way to do this:
// JSON Data parsed into JS Object
var arr = JSON.parse('[{"lastname":"Stark","firstname":"Tony","id":1},{"lastname":"Parker","firstname":"Peter","id":2},{"lastname":"Rogers","firstname":"Steve","id":3}]');
var newArr = [];
for(var i=0; i<arr.length; i++)
newArr.push({"fullname": arr[i]["firstname"] + " " + arr[i]["lastname"], "id": arr[i]["id"]});
console.log(JSON.stringify(newArr)); // Convert to text for JSON.

javascript count number values repeated in a jsonArray items

i need to count the number of occurrences of values in jsonArray items in javascript.
consider this as my jsonArray:
{"name":"jack","age":23},
{"name":"john","age":20},
{"name":"alison","age":23},
{"name":"steve","age":25},
.
.
.
now for example i need to know how many times each age is repeated in this array, i want to count each value for each property, i mean i need a result like this :
name : {"jack" : 2,"james" : 10,"john" : 1,....}
age : {"23":10,"20":15,"25":2,....}
what is the simplest way to achieve this?
EDIT :
my array is very big and i don't want to call count function for each value. i want a code to count each value repeat times.
you can have a look at Array.prototype.reduce
function mapToProp(data, prop) {
return data
.reduce((res, item) => Object
.assign(res, {
[item[prop]]: 1 + (res[item[prop]] || 0)
}), Object.create(null))
;
}
const data = [
{"name": "jack", "age": 23},
{"name": "john", "age": 20},
{"name": "alison", "age": 23},
{"name": "steve", "age": 25}
];
console.log('mapAndCountByAge', mapToProp(data, 'age'))
You could use an object, where the keys and the values are used as property for the count.
var array = [{ name: "jack", age:23 }, { 'name': "john", age: 20 }, { name: "alison", age: 23 }, { name: "steve", age: 25 }],
result = {};
array.forEach(function (o) {
Object.keys(o).forEach(function (k) {
result[k] = result[k] || {};
result[k][o[k]] = (result[k][o[k]] || 0) + 1;
});
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Not as elegant as Nina's and Hitmands' answers, but this is easier to understand for beginners (in case any beginner is reading this).
var jsonArray = [
{"name": "John", "age": 20},
{"name": "John", "age": 21},
{"name": "Doe", "age": 21},
{"name": "Doe", "age": 23},
{"name": "Doe", "age": 20},
];
var names = [],
ages = [];
// separate name data and age data into respective array
// only need to access the original data once
jsonArray.forEach(function(val){
names.push(val['name']);
ages.push(val['age']);
});
function aggregate(array){
var obj = {};
array.forEach(function(val){
if (!obj[val])
// create new property if property is not found
obj[val] = 1;
else
// increment matched property by 1
obj[val]++;
});
return JSON.stringify(obj);
}
console.log("Names: " + aggregate(names));
console.log("Ages: " + aggregate(ages));
In my opinion, Nina has the best answer here.
EDIT
In fact, when presented with large dataset (as OP stated that "the array is very big"), this method is about 45% faster than Nina's answer and about 81% faster than Hitmand's answer according to jsben.ch. I don't know why though.

javascript filter of array with titles

I have the following code (using Chrome)
<script>
var arr = [{
"id": 1,
"fn": "bill",
"ln": "blogs"
}, {
"id": 2,
"fn": "jim",
"ln": "jones"
}, {
"id": 3,
"fn": "bill",
"ln": "smith"
}];
var lookFor = "bill";
var result = arr.filter(function(item) {
return if (item.ln == lookFor) return true;
});
alert(result.length);
alert(result[0]["id"] + result[0]["fn"] + result[0]["ln"]);
</script>
I am trying to filter the array and return those that the first name (fn) is bill. Returning id, fn, and ln in a messagebox.
I am probably missing some knowledge of the syntax of this.
Try this
var result = arr.filter(function(item) {
return item.fn === lookFor;
});
....return those that the first name (fn) is bill
But in your code you use item.ln. Also why do you use two return statement
return if (item.ln == lookFor) return true;
You need just return true or false and you can do it like this
return item.fn === lookFor;
if item.fn equals lookFor it will be true, otherwise false
Example
You should be using
var arr = [{
"id": 1,
"fn": "bill",
"ln": "blogs"
}, {
"id": 2,
"fn": "jim",
"ln": "jones"
}, {
"id": 3,
"fn": "bill",
"ln": "smith"
}];
var lookFor = "bill";
var result = arr.filter(function(item) {
return item.ln === lookFor;
});
alert(result.length);
alert(result[0]["id"] + result[0]["fn"] + result[0]["ln"]);
But I guess its not ln which you want, instead you want fn cause their is no ln which is equal to bill.

JSON/JavaScript - Getting value by passing index and property name

For the following JSON:
var myJSON =
{ "employee": [
{
"firstName": "John",
"lastName": "Doe",
"Age": 20
},
{
"firstName": "Jane",
"lastName": "Moe",
"Age": 35
},
{
"firstName": "Mike",
"lastName": "Poe",
"Age": 28
}
]
};
Let's say I need to grab a particular value by passing an index and a property name. For example, employee[1].lastName would give me the value "Moe". But, I'm having some rough time figuring out what's supposed to be a simple JavaScript function that takes these two values as input and returns the value as output. The following code doesn't seem to work:
function getValue(index, attrName) {
var val = eval("myJSON.employee[" + index + "]." + attrName); // is using eval() even a sound approach?
return val;
}
This should do it.
var myJSON =
{ "employee": [
{
"firstName": "John",
"lastName": "Doe",
"Age": 20
},
{
"firstName": "Jane",
"lastName": "Moe",
"Age": 35
},
{
"firstName": "Mike",
"lastName": "Poe",
"Age": 28
}
]
};
function getValue(index, attrName) {
return myJSON['employee'][index][attrName];
}
getValue(1,'lastName')
Outputs: "Moe".
Attribute accessors var['attr'] and var.attr are identical, except that some attribute names cannot be expressed like var.attr. Suppose your attribute name is "foo-bar". The code var.foo-bar is not correct so you'd have to use var['foo-bar']. Also, you can address global variables with window['var-name'].

Categories

Resources