Totalling/merging JavaScript values based on key - javascript

I have a JavaScript array which I use jQuery to display values in a table
for (var i = 0; i < data.MyArray.length; i++) {
$('#my-table').append('<tr><td>' + data.MyArray[i].DisplayGroup + '</td><td>' + data.MyArray[i].Value + '%<td></tr>');
}
I would like to "group" the values based on DisplayGroup prior to displaying the values
So if my array contains
DisplayGroup: ABC Value: 5
DisplayGroup: DEF Value: 3
DisplayGroup: ABC Value: 6
DisplayGroup: GHI Value: 2
I would like to total the duplicate DisplayGroup entries (in this example ABC) so that I display
ABC 11
DEF 3
GHI 2
Is there a way to iterate through the array and create a new array to then use?

var array = [{
DisplayGroup: 'ABC',
Value: 5
}, {
DisplayGroup: 'DEF',
Value: 3
}, {
DisplayGroup: 'ABC',
Value: 6
}, {
DisplayGroup: 'GHI',
Value: 2
}];
Array.prototype.groupBy = function( key,value){
var newArray = []
var temp = []
this.filter((c,i,a)=> {
var ob = {}
if(temp.indexOf(c[key]) == -1){
ob[c[key]] = c[value] ;
newArray.push(ob)
temp.push(c[key]);
}
else{
newArray.filter((e)=> {
if(e[c[key]]){
e[c[key]] = e[c[key]] + c[value]
}
});
}
})
return newArray;
}
console.log(array.groupBy('DisplayGroup','Value'))

Is there a way to iterate through the array and create a new array to then use?
There's no need to create a new array, you can just use array reduction to create an object that contains all the data. The approach you can take is to iterate through the array and build the object by initializing not yet found values and incrementing the already initialized:
var convertedObject = arr.reduce(function(obj, item) {
var g = item.DisplayGroup;
var v = item.Value;
if (typeof obj[g] !== 'number') {
obj[g] = v; // initialize value that wasn't found yet
} else {
obj[g] += v; // update the value with the current increment
}
return obj;
}, {});
Then you can build the table using a similar loop to the one you have:
$.each(convertedObject, function(key, value) {
table.append('<tr><td>' + key + '</td><td>' + value + '<td></tr>');
});
Here's a running example:
var arr = [{
DisplayGroup: 'ABC',
Value: 5
}, {
DisplayGroup: 'DEF',
Value: 3
}, {
DisplayGroup: 'ABC',
Value: 6
}, {
DisplayGroup: 'GHI',
Value: 2
}];
// reducing into an object
var convertedObject = arr.reduce(function(obj, item) {
var g = item.DisplayGroup;
var v = item.Value;
if (typeof obj[g] !== 'number') {
obj[g] = v; // initialize value that wasn't found yet
} else {
obj[g] += v; // update the value with the current increment
}
return obj;
}, {});
var table = $('#table');
$.each(convertedObject, function(key, value) {
table.append('<tr><td>' + key + '</td><td>' + value + '<td></tr>');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="table">
</table>
If you need to, this is how you can convert this object into an array:
var convertedArray = Object.keys(convertedObject).map(function(key) {
var obj = {};
obj[key] = object[key];
return obj;
});

Related

Check if key exist in array by pushing values

Can someone tell me why everytime I want to check if a key is avalaible inside my array the result that I get is false? See my example below
var obj = new Array();
obj.push({ name: "test1", value: "10" });
obj.push({ name: "test2", value: "40" });
//var inobject = "name" in obj; // result: false
//var inobject = "test1" in obj; // result: false
//var inobject = "10" in obj; // result: false
var inobject = "value" in obj;
$('body').append("<p>"+ inobject + "</p>");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
You are checking if "value" exists in the array and not in elements of your array. To correctly check if "value" exists in an element of the array you need to address obj[i]. Like this:
var obj = new Array();
obj.push({ name: "test1", value: "10" });
obj.push({ name: "test2", value: "40" });
var inobject = "value" in obj[0];
console.log(inobject);
If you want to find a key exist in any of the object, (first level) in a collection then instead of doing
"value" in obj; you can do obj.some(e=> "value" in o);
//name is obj but its actually a array
var obj = new Array();
obj.push({ name: "test1", value: "10" });
obj.push({ name: "test2", value: "40" });
function checkForKey(list, key) {
return list.some(e => key in e);
}
console.log('Key [name]:', checkForKey(obj, 'name'));
console.log('Key [age]:', checkForKey(obj, 'age'));
console.log('Key [value]:', checkForKey(obj, 'value'));
If you are looking at any level, inside either an array or object recursively, then try this, (not much performance efficient but easy to manipulate)
var obj = new Array();
obj.push({ name: "test1", value: "10" });
obj.push({ name: "test2", value: "40" });
function checkForKeyNested(list, key) {
try {
JSON.parse(JSON.stringify(list), function(k, v){
if(key===k) {
flag=true;
throw 0;
}
return v;
});
} catch(ex) { return true;}
return false;
}
console.log('Key [name]:', checkForKeyNested(obj, 'name'));
console.log('Key [age]:', checkForKeyNested(obj, 'age'));
console.log('Key [value]:', checkForKeyNested(obj, 'value'));
You can only search for keys of the array or values like this:
var obj = new Array(),
el1, el2
obj.push(el1 = { name: "test1", value: "10" });
obj.push(el2 ={ name: "test2", value: "40" });
$('body').append("<p>check for key 1: "+ (1 in obj) + "</p>");
$('body').append("<p>check for element el1: "+ (obj.indexOf(el1) >= 0) + "</p>");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
If you are searching an element inside the array that meets other criteria you have to do something like this:
var obj = new Array();
obj.push({ name: "test1", value: "10" });
obj.push({ name: "test2", value: "40" });
// direct object access
var inobject = obj.filter((e)=>{ return 'value' in e && e.value == 10}).length > 0;
// deconstruct elements for better readability (WARNING: object deconstruction is not supported in all browsers yet!)
var inobject2 = obj.filter(({name, value})=>{ return 'value' !=undefined && value == 10}).length > 0;
$('body').append("<p>Search for element with value = 10: "+ inobject + "</p>");
$('body').append("<p>Search for element with value = 10: "+ inobject2 + "</p>");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
You May try for this.
var obj = new Object();
obj.name='t1';
obj.value='t2';
obj.hasOwnProperty('value'); // Return true if exist otherwise false
The problem is that you are trying to check if the key exists on the Array, rather than on the objects within the array, so as expected those keys do not match as they don't exist on the array.
If you are trying to check if any objects within an array has a specific key, then you can do this with a simple loop:
var found = false;
var search = "value";
for(var i = 0; i < obj.length; i++){
if(search in obj[i]){
found = true;
break;
}
}
Or separate it into a nice function:
function doesKeyExist(var arr, var key){
for(var i = 0; i < obj.length; i++){
if(key in obj[i])
return true;
}
return false;
}
var inobject = doesKeyExist(obj, "value");
$('body').append("<p>"+ inobject + "</p>");
If you want to find the value of a property, you can do this:
function doesValueExistForKey(var arr, var key, var search){
for(var i = 0; i < obj.length; i++){
if(key in obj[i] && obj[i][key] === search)
return true;
}
return false;
}
var inobject = doesValueExistForKey(obj, "name", "test1");
$('body').append("<p>"+ inobject + "</p>");
Because "value" in obj isn't the way you check a value's existence in an array, and you have an array of objects, which means you have to check the existence against the array's elements not the array itself, this is how you do it :
var obj = new Array();
obj.push({ name: "test1", value: "10" });
obj.push({ name: "test2", value: "40" });
var inobject = obj.some((a) => "value" in a);
console.log(inobject); // true, means it's there
If you want to get the elements that have the key "value", use :
var obj = new Array();
obj.push({ name: "test1", value: "10" });
obj.push({ name: "test2", value: "40" });
obj.push({ name: "test2", AnotherKey: "60" });
var objects = obj.filter((a) => "value" in a);
console.log(objects); // test1 and test2
The in operator checks for property key names of the object it is called on. You can use it on the objects you pushed into the array, or use it with the array indexes.
// a little nano-sized test suite made on the fly :)
const passed = document.getElementById('passed')
const assert = test => {
if (!test) throw 'invalid assertion'
passed.innerText = +passed.innerText + 1
}
// creates an Object that inherits from Array.prototype
var obj = new Array()
// Append an object {name, value} to the array
//
obj.push({
name: 'test1',
value: 10
})
// Add a property to the array-object called value
obj.value = 40
assert('name' in obj === false)
assert('value' in obj === true)
assert(0 in obj === true)
assert('name' in obj[0] === true)
<p><span id='passed'>0</span> tests passed</p>
You are working with an array of objects. Several ways to do this, but let's simply create a lookup and lookupAll function and use it: (they both return arrays of objects) the others return index and indexes array - changes if you sort. Note this works, even in very much ugly older browsers like IE6.
// create a namespace for my functions
var myApp = myApp || {};
myApp.arrayObj = {
indexOf: function(myArray, searchTerm, property) {
for (var i = 0; i < myArray.length; i++) {
if (myArray[i][property] === searchTerm) return i;
}
return -1;
},
indexAllOf: function(myArray, searchTerm, property) {
var ai = [];
for (var i = 0; i < myArray.length; i++) {
if (myArray[i][property] === searchTerm) ai.push(i);
}
return ai;
},
lookup: function(myArray, searchTerm, property, firstOnly) {
var found = [];
var i = myArray.length;
while (i--) {
if (myArray[i][property] === searchTerm) {
found.push(myArray[i]);
if (firstOnly) break; //if only the first
}
}
return found;
},
lookupAll: function(myArray, property, searchTerm) {
return this.lookup(myArray, searchTerm, property, false);
}
};
var myobj = [{ name: "friend", value: "17" }];// better than new Array()
myobj.push({ name: "test1", value: "10" });
myobj.push({ name: "test2", value: "40" });
console.log(myobj);
// array of all matches
var allones = myApp.arrayObj.lookupAll(myobj, "test1", "name");
console.log(allones.length);// 1
// returns array of 1
var firstone = myApp.arrayObj.lookup(myobj, "friend", "name",true);
console.log(firstone[0].value);//17
The in operator checks for keys. Your array has the following keys:
0,1
So
0 in obj
is true.

Multiple data in array but only sort by name

I have an array currently only with names because I cannot figure out how to add more information but not make the script sort that data. For every entry in the array I wish to add a number between 1-20 for each, and also a count of how many is named that name. So it would something like 1. Nielsen (100,000). It's only a problem with my second function because I need to sort it by length.
<script>
var arr = []
arr[0] = " Nielsen"
arr[1] = " Jensen"
arr[2] = " Hansen"
arr[3] = " Pedersen"
arr[4] = " Andersen"
arr[5] = " Christensen"
arr[6] = " Larsen"
arr[7] = " Sørensen"
arr[8] = " Rasmussen"
arr[9] = " Jørgensen"
arr[10] = " Petersen"
arr[11] = " Madsen"
arr[12] = " Kristensen"
arr[13] = " Olsen"
arr[14] = " Thomsen"
arr[15] = " Christiansen"
arr[16] = " Poulsen"
arr[17] = " Johansen"
arr[18] = " Møller"
arr[19] = " Mortensen"
document.getElementById("liste").innerHTML = arr; // Skriver den oprindelige rækkefølge
function Sorter1() {
arr.sort(); // Sorter efter aflabetisk rækkefølge
document.getElementById("liste").innerHTML = arr; // Skriver rækkefølgen
}
function Sorter2() {
arr.sort(function (a, b) {
return b.length - a.length || // sorter efter længde
a.localeCompare(b); // Sorter efter aflabetisk rækkefølge
});
document.getElementById("liste").innerHTML = arr; // Skriver rækkefølgen
}
</script>
If I understand you correct you would like to create a multidimensional array and then sort it on the name alphabetically and on character count. If that is correct I would suggest you to create an multidimensional object with the data needed. Then you will be able to sort on the name key and preserve the other information correctly.
Check this out, it may get you in the right direction
var arr = [
{
name: 'Nielsen',
num: 1,
count: 100
},
{
name: 'Jensenlongest',
num: 15,
count: 230
},
{
name: 'Jensenlong',
num: 13,
count: 500
},
{
name: 'Jensen',
num: 2,
count: 300
},
{
name: 'Hansen',
num: 5,
count: 400
}
]
// Just adds the unsorted arr to the list for demo purpose
updateList(arr)
// On "Sort by length" button click
document.getElementById('sort-by-length').addEventListener('click', function (event) {
arr.sort(sortNameByLength);
updateList(arr);
})
// On "Sort alphabetically" button click
document.getElementById('sort-alphabetically').addEventListener('click', function (event) {
arr.sort(sortNameAlphabetically);
updateList(arr);
})
// Sort by name alphabetically
function sortNameAlphabetically(a, b) {
return a.name > b.name
}
// Sort by name length
function sortNameByLength(a, b) {
return a.name.length - b.name.length
}
// Updates the list according to the current sorting of the arr
function updateList(names) {
var listHtml = ''
names.forEach(function (item, index) {
listHtml += item.name + ', ' + item.num + ' (' + item.count + ')<br>'
})
document.getElementById("liste").innerHTML = listHtml
}
https://jsfiddle.net/sbe8yzv0/4/
This will result in a list like this.
Hansen, 5 (400)
Jensen, 2 (300)
Jensenlong, 13 (500)
Jensenlongest, 15 (230)
Nielsen, 1 (100)
You can use an array of complex objects with the data structure you like (just be consistent). Then define your own sort() method that will compare only the name parameter of your objects. Here's a simple example:
var arr = [];
arr[0] = {ID: 1, Name: "Nielsen", Value: "100"};
arr[0] = {ID: 2, Name: "Jensen", Value: "200"};
// Sort based on the second column, 'Name'.
function sortByName(){
arr.sort(
function(x, y){
return x.Name > y.Name; // Compare and sort based on the 'Name' column only.
}
);
console.log(arr[0]); // If results are correct this is 'Jensen'.
console.log(arr[1]); // If results are correct this is 'Nielsen'.
}
Adapt this to your needs (add the proper columns and data, add the proper variables, make it so that it shows in your page's HTML) and it will do what you want.

javascript foreach return results containing name

I have the below javascript which returns the name1 value for each item.
var data = [{"name1": "aaa", "name2":"bbb", "other":"ccc"},{"name1": "ddd", "name2":"eee", "other":"fff"}];
function logArrayElements(element, index, array) {
contName = element.name1;
console.log('a[' + index + '] = ' + contName);
}
data.forEach(logArrayElements);
//returns below in console
a[0] = aaa
a[1] = ddd
I want to return all values containing name for each item.
I could do this by adding in
contName2 = element.name2;
console.log('a[' + index + '] = ' + contName);
However I don't want to list it out as I will have a different amount of 'names' on different occasions.
I know when searching for a string I can do the below, but can't work out how to work something similar into what I have above?
var myName = "name2";
console.log(myName.indexOf("name") > -1);
You can use array.filter and then walk each of the objects in the array like so:
var myArray = [
{"name1": "aaa", "name2":"bbb", "other":"ccc"},
{"name1": "ddd", "name2":"eee", "other":"fff"}
];
myArray.filter(function(row){
for( key in row ){
if( key.indexOf('name') === 0 ){ // only matches keys **starting** with "name"
console.log( 'a[' + key + '] = ' + row[key] );
}
}
});
Here is what I would do.
I would loop through your object's keys to find those who start with 'name' :
function logArrayElements(element, index, array) {
for(var i in element){
if(i.indexOf('name') === 0){
contName = element[i];
console.log('a[' + index + '] = ' + contName);
}
}
}
I know I'm a little late in the game, but I just wanted to add another alternative to the mix using lodash.
var data = [{
"name1": "aaa",
"name2": "bbb",
"other": "ccc"
}, {
"name1": "ddd",
"name2": "eee",
"other": "fff"
}];
function getFields(data, expression) {
var re = new RegExp(expression, "i");
return _.reduce(data, function(result, object) {
return _.union(result, _.reduce(object, function(list, value, key) {
if (re.test(key)) {
return _.union(list, [value]);
} else {
return list;
}
}, []));
}, []);
}
alert(getFields(data, '^name'));
alert(getFields(data, '^other'));
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.js"></script>
This function above returns all the names found as an array. The function accepts two arguments: the array to be searched and a regular expression to match the key names of the values to be returned.

How to parse form data to work with JSON in jQuery?

var checkedValues = $('.required:checked').map(function () {
return this.value;
}).get();
var arr = new Array(10);
alert(checkedValues);
alert("number of values in it " +checkedValues.length);
if (checkedValues.length > 1) {
alert("I am inside if ");
arr = checkedValues.split(',');
alert("I am done with the split ");
}
else {
arr = checkedValues;
alert("No split needed ");
}
$.getJSON('#Url.Action("testcata", "home")' + + '?Type=' + "#(Session["typ"])" + "&city=" + "#(Session["cit"])" + "&chkd=" + checkedValues,
function (data) {
//code
})
In controller :
public ActionResult testcata(string Type, int? city, int[] chkd)
{
//code
}
I am trying to get the values of check-boxes which are checked and store them in array which are then sent to controller through json function. alert("I am done with the split") is not being shown . Please help me.
Have a look at .serializeArray():
var checkedValues = $('.required:checked').serializeArray();
It returns an array ready for JSON, like so:
[
{
name: "a",
value: "1"
},
{
name: "b",
value: "2"
},
{
name: "c",
value: "3"
},
{
name: "d",
value: "4"
},
{
name: "e",
value: "5"
}
]
split works on string .you can use split on each array index not on whole array.
if you really want to split array checkedValues then loop through this array then use split on each index.
like this:
for( var i=0; i< checkedValues.length;i++){
var arr = checkedValues[i].split(',');
// use arr for requrement.
}
Try
// array of values
var arr = [];
$(".required")
.on("change", function (e) {
// `checked` `.required` elements
var checkedValues = $(this).prop("checked");
// `if` `checkedValues` (any `required` elements `checked`) , continue
if (checkedValues) {
// populate `arr` with `.required` `checked` values
arr.push(checkedValues);
// do stuff with `arr`
// `console.log` values in `arr` , `arr` length
console.log("array of values: " + arr
, "array of values length: " + arr.length);
};
});
jsfiddle http://jsfiddle.net/guest271314/d332nfkh/

Find minimum value in javascript?

I want to print the minimum variable 'name' in JS. Currently it prints the minimaum value. I rather want the variable name. For eg:- In the current code, it gives me 4, but I want c. How can I do this?
<script>
function myFunction()
{
var a = 5;
var b =10;
var c = 4;
document.getElementById("demo").innerHTML=Math.min(a,b,c);
}
</script>
Working DEMO
This should do the trick:
//Push values to object
var age = {};
age.a = 5;
age.b = 10;
age.c = 4;
var min = Infinity, name;
// Loop through object to get min value and then find relevant name
for(var x in age) {
if( age[x] < min) {
min = age[x];
name = x;
}
}
console.log ( 'property name is ' + name + ' and value is ' + min );
You could put your values in an array like
var values = [
{ name: 'a', value: 5 },
{ name: 'b', value: 10 },
{ name: 'c', value: 4 }
];
and then use the filter method with the hint from Ahmad's comment:
var min_value = Math.min.apply(null, values.map(function(item) {
return item.value;
}));
var min_name = values.filter(function (item) {
return item.value == min_value;
})[0].name;
See this fiddle for a working example.
Store the values in an array of objects. Each object will contain a name and value property. Then just iterate through the values and store the lowest.
var values = [
{
"name": "a",
"value": 5
},
{"name":"b",
"value":10
},
{
"name":"c",
"value":4
}
];
function min(arr){
var minValue = {};
for(var x = 0; x < arr.length; x++){
if(arr[x].value < minValue.value || !minValue.value){
minValue = arr[x];
}
}
return minValue.name;
};
document.getElementById("demo").innerHTML = min(values);
JS Fiddle: http://jsfiddle.net/AgMbW/
You can do this way:
var obj = {"names":["a","b","c"], "values":[5,10,4]}
var min = Math.min.apply( Math, obj["values"] );
var result = obj["names"][obj["values"].indexOf(min)];
document.getElementById("demo").innerHTML=result;
Here the fiddle: http://jsfiddle.net/eUcug/
Way 1 :
var x = 5;var getName = function(value){if(value === 5) return 'x'; else return null}
Way 2 :
NameValue.getName = function(value){for(i = 1;i<=2;i++){if(this["val" + i].value === value) {return this["val" + i].name;break;}console.log(this["val" + i]);}return null;}NameValue.val2 = {name : 'y',value : 1};NameValue.prototype.add({name : 'x',value : 10})
NameValue.getName(10); //return "x"
I hope you can understand how to find the variable name.

Categories