javascript array - increment value at given key - javascript

I have a dynamic array and I am trying to increment the value by 1 if the key exists in the array. According to my debug it is incrementing the key and and creating a second key/value pair.
A snippet of my code:
for (var i = 0; i < choices.length; i++) {
console.log(choices[i]);
if (choices[i].YearTermId == 1) {
if (!lookup(firstChoice, choices[i].FirstChoiceOptionId)) {
firstChoice.push({
key: choices[i].FirstChoiceOptionId,
value: 1
});
} else {
firstChoice[choices[i].FirstChoiceOptionId] = firstChoice[choices[i].FirstChoiceOptionId] + 1;
}
more if/else..
function lookup( arr, name ) {
for(var i = 0, len = arr.length; i < len; i++) {
if( arr[ i ].key === name )
return true;
}
return false;
}

You're using an array where you should be using an object. If you use an object, your code can be rewritten as:
var firstChoice = {};
for (var i = 0; i < choices.length; i++) {
var firstChoiceOptionId = choices[i].FirstChoiceOptionId;
if (choices[i].YearTermId == 1) {
firstChoice[firstChoiceOptionId] = firstChoice[firstChoiceOptionId]
? firstChoice[firstChoiceOptionId] + 1
: 1;
/* ... */
}
}
If you need the data as an array afterwards, just map it:
var firstChoiceArray = Object.keys(firstChoice).map(function(key) {
return {
key: key,
value: firstChoice[key]
};
});
Conversely, if you have an input array and want to convert it to an object for manipulation, reduce it:
var firstChoice = firstChoiceArray.reduce(function(result, current) {
result[current.key] = current.value;
return result;
}, {});

I think you should increment value key, like:
firstChoice[choices[i].FirstChoiceOptionId].value ++;
And I would like to rewrite this code to:
var firstChoice = {};
for (var i = 0; i < choices.length; i++) {
if (choices[i].YearTermId == 1) {
if (!firstChoice[choices[i].FirstChoiceOptionId]) {
firstChoice[choices[i].FirstChoiceOptionId] = 0;
}
firstChoice[choices[i].FirstChoiceOptionId]++;
}
}
console.log(firstChoice);

Try with Array.map:
Example:
var a = [{key:"ab","value":1},{key:"cd","value":1},{key:"ef","value":1}];
a.map(function(item){if(item.key == this){item.value++}}, "cd");
So, a[1] will have value 2 after that.

Related

How do I build an object counting occurrences in an Array in JavaScript?

I want to count how often a number in an Array occurs. For example, in Python I can use Collections.Counter to create a dictionary of how frequently an item occurs in a list.
This is as far as I've gotten in JavaScript:
var array = [1,4,4,5,5,7];
var obj = {};
for (var i=0; i < array.length; i++) {
/* obj[array[i]] = +=1 */ <= pseudo code
}
How can I create this frequency counter object?
Close but you can't increment undefined so you need to set initial value if it doesn't exist
var array = [1,4,4,5,5,7];
var obj = {};
for (var i=0; i < array.length; i++) {
obj[array[i]] = (obj[array[i]] || 0) +1 ;
}
You were almost there. See below code:
var array = [1,4,4,5,5,7];
var obj = {};
for (var i=0; i < array.length; i++) {
obj[array[i]] = (obj[array[i]] || 0 ) +1;
}
console.log(obj);
Create an object and check if that specific key exist.If exist then increase it's value by 1
var array = [1, 4, 4, 5, 5, 7];
var obj = {};
for (var i = 0; i < array.length; i++) {
if (obj.hasOwnProperty(array[i])) {
obj[array[i]] += 1;
} else {
obj[array[i]] = 1;
}
}
console.log(obj)
You can use the ? : ternary operator to set initial value as 1 and then increment it on subsequent matches.
var array = [1,4,4,5,5,7];
var obj = {};
for (var i=0; i < array.length; i++) {
obj[array[i]] = obj[array[i]]?obj[array[i]]+1:1;
}
console.log(obj);
If the array is always going to be same, and you are going to check frequency of multiple items in the same array without it it being modified, #JohanP's answer is good.
But if you are only going to check frequency of only one item, or the array can change, creating the object is nothing but extra overhead.
In that case, you can do something like this:
const getItemFrequency = function(array, item) {
return array.filter(i => i === item).length;
}
var array = [1,4,4,5,5,7];
console.log(getItemFrequency(array, 4));
Concise logic written as proper function:
function countArrayItemFrequecy(array) {
const length = array.length;
const map = {};
for ( let i = 0; i < length; i++ ) {
let currentItem = array[i];
if (typeof map[currentItem] !== 'undefined' ) {
map[currentItem]++
} else {
map[currentItem] = 1
}
}
return map;
}
You need to make sure to assign default value to your frequency object for the first occurrence of the item. As a shortcut you can use ternary operator
var array = [1,4,4,5,5,7];
var obj = {};
for (var i=0; i < array.length; i++) {
obj[array[i]] = obj[array[i]] ? obj[array[i]]++ : 1;
}
which is the same as:
var array = [1,4,4,5,5,7];
var obj = {};
for (var i=0; i < array.length; i++) {
if (obj[array[i]]) {
obj[array[i]]++;
} else {
obj[array[i]] = 1;
}
}
You can use Object.assign: below clones map and then increments/adds the counter. These are pure (no side effects/param reassignment), single-purpose functions.
addToMap does the same thing as { ...map, map[e]: [e]: (map[e] || 0) + 1 }, but that requires babel.
const addToMap = (map, e) => Object.assign({}, map, { [e]: (map[e] || 0) + 1 });
const buildMap = a => a.reduce(addToMap, {});
Using Array.reduce:
arr.reduce(function (acc, item) {
acc[item] = (acc[item] || 0) + 1;
return acc;
}, {});
Example:
var arr = [1,1,2,4,1,4];
var counts = arr.reduce(function (acc, item) {
acc[item] = (acc[item] || 0) + 1;
return acc;
}, {});
console.log(counts);

Object doesn't return the maximum number - JS

I was trying to return the maximum repeated word. However for some reason it doesn't return the max. Here's the code responsible for that:
var max = -Infinity;
for(var prop in myObj){
if(myObj[prop] > max){
max = prop;
}
}
return max;
This one returns "h" w/c is the first element in the word 'helllo'...it supposed to be 'l'...
Right now here's my whole codes:
function findMaxRepeatCountInWord(word) {
var splitWord = word.split('');
var myObj = {};
for(var i = 0; i < splitWord.length; i++){
if(myObj.hasOwnProperty(splitWord[i])){
myObj[splitWord[i]]++;
}else{
myObj[splitWord[i]] = 1;
}
}
var max = -Infinity;
for(var prop in myObj){
if(myObj[prop] > max){
max = prop;
}
}
return max;
}
console.log(findMaxRepeatCountInWord('helllo'));
Any idea what am I missing out?
You are comparing a value at first and then you change max to a key.
I suggest to use max only for the key, with a initializing with the first element of the keys. Then iterate from the second key and check if the value is gereater then the actual max value.
function findMaxRepeatCountInWord(word) {
var splitWord = word.split('');
var myObj = {};
for (var i = 0; i < splitWord.length; i++) {
if (myObj.hasOwnProperty(splitWord[i])) {
myObj[splitWord[i]]++;
} else {
myObj[splitWord[i]] = 1;
}
}
var keys = Object.keys(myObj), // take the keys in an array
max = keys[0]; // initialize with the first key
for (i = 1; i < keys.length; i++) { // iterate from the second key
if (myObj[keys[i]] > myObj[max]) { // check and
max = keys[i]; // update
}
}
return max;
}
console.log(findMaxRepeatCountInWord('helllo'));
max is one of the keys. You should compare the value of that key with the current key prop:
if(myObj[prop] > myObj[max])
// ^^^^^^ ^
Simply loop through each character of the text, then store the occurrence in an object
var getMaxOccurence = function (text)
{
var maxObj = {};
// loop through each character
for (var i = 0; i < text.length; i++)
{
var char = text.charAt(i);
// check if char is in obj
if (!(char in maxObj))
{
// add occurrence
maxObj[char] = 1;
}
else
{
// add occurrence
maxObj[char]++;
}
}
var max = {
value: 0,
key: 0
};
var keys = Object.keys(maxObj);
// here get which character contains the highest value.
for (var i = 0; i < keys.length; i++)
{
if (maxObj[keys[i]] > max.value)
{
max.value = maxObj[keys[i]];
max.key = keys[i];
}
}
// return it
return max;
};
document.getElementById("subject").innerHTML = "helllo";
var result = getMaxOccurence("helllo");
document.getElementById("result").innerHTML = result.key + " ( " + result.value + " ) ";
Subject: <span id="subject"></span>
<br/>
Max occurence: <span id="result"></span>
hope that helps

How can I return the longest string in an array—even if the array contains items that are not strings?

Let's say I'm writing a function like so:
function longestString (someArray) {
// code
}
If someArray = ['word','longer phrase',['a','b','c'],1234567891011121314151617], I would want the function to only return the longest string in the array and ignore the integers and other arrays that may also lie within it. I tried this:
function longestString (someArray) {
return someArray.sort(function (a, b) { return b.length - a.length; })[0];
}
It didn't work, and I am now stuck. :/
Filter only string element and do it
function longestString (someArray) {
return someArray
.filter(function(a){ return typeof(a)=='string' })
.sort(function (a, b) { return b.length - a.length; })[0];
}
Try this:
function longestString(someArray) {
var result = "";
for (var i = 0; i < someArray.length; i++) {
if ((typeof someArray[i] === "string") && (someArray[i].length > result.length)) {
result = someArray[i];
}
}
return result;
}
try to do :
function longestString (someArray) {
$longest_string = '';
foreach ($someArray as $value)
{
$current_length = strlen($longest_string);
if(strlen($value) > $current_length ) $longest_string = $value;
}
return $longest_string;
}
Try this.
var a = ['word', 'longer phrase', ['a', 'b', 'c'], 1234567891011121314151617];
returnLongestString(a);
function returnLongestString(arr) {
var longestString = '';
for (var i = 0; i < arr.length; i++) {
if (typeof arr[i] == "string" && arr[i].length > longestString.length) {
longestString = arr[i];
}
};
return longestString;
}
When I saw this question, it had 0 answers, when I finished writing and testing my function, there were five. But this is my approach:
The key here is to first filter only the strings. Then, list all the lengths on an array. Then using that array you can get a match on the bigger one.
function longestString (someArray) {
//we only need strings, so first we will filter all the data
var stringsOnly = [];
for (var i = 0; i < someArray.length; i++) {
if(typeof(someArray[i]) === 'string'){
stringsOnly.push(someArray[i]);
}
};
//Now with an array of just strings, we can get their indivial lenghts
var stringLengths = [];
for (var i = 0; i < stringsOnly.length; i++) {
var currentString = stringsOnly[i];
stringLengths.push(currentString.length);
};
//Get the max length
var maxLength = Math.max.apply(Math,stringLengths);
//get a string wich length equals to maxLength
for (var i = 0; i < stringsOnly.length; i++) {
var theString = stringsOnly[i];
if(theString.length === maxLength){return theString};
};
}
This function will return the largest string. If more than one string have the same length, It will return the first one. However, if you want to get various strings, you could make some little modificationson the function above:
function multipleLongestString (someArray) {
//we only need strings, so first we will filter all the data
var stringsOnly = [];
for (var i = 0; i < someArray.length; i++) {
if(typeof(someArray[i]) === 'string'){
stringsOnly.push(someArray[i]);
}
};
//Now with an array of just strings, we can get their indivial lenghts
var stringLengths = [];
for (var i = 0; i < stringsOnly.length; i++) {
var currentString = stringsOnly[i];
stringLengths.push(currentString.length);
};
//Get the max length
var maxLength = Math.max.apply(Math,stringLengths);
//modification here
longests = [];
//get a string wich length equals to maxLength
for (var i = 0; i < stringsOnly.length; i++) {
var theString = stringsOnly[i];
if(theString.length === maxLength){longests.push(theString)};
};
return longests;
}
That is an extra that may help you later. But if you just want the largest one, use the first function. I hope that my answer is relevant.
:)
Heres my approach at it. Really all you want to know is if the phrase is longer than the previous and if its a string.
jsFiddle here.
var someArray = ['word','longer phrase',['a','b','c'],1234567891011121314151617]
var longestString = function(arr) {
var longest = "";
for (var i = 0; i < arr.length; i++) {
var value = arr[i];
if (typeof value === "string") {
longest = arr[i];
}
}
alert(longest);
}
longestString(someArray);

JS array string patch name to array(object)

i have trouble with js array.
I have patch name(string) look like ( "user.joey.friends.0.franc" ) and i need to "compress" to look like this:
console.log( parseArray( "user.joey.friends.0.franc" ) );
//Object {
user: {
joey: {
friends: {
0: {
franc: 1
}
}
}
}
}
Any ideas, how to do that ?
Here's a non recursive way to get you most of the way there.
function compress(str) {
var split = str.split('.'), obj = {}, current = obj, i;
for (i = 0; i < split.length; i++){
current[split[i]] = {} ;
current = current[split[i]];
}
return obj;
}
If you're saying you have an object with the structure you've quoted, and you're trying to look up the property defined by your string "user.joey.friends.0.franc", that's a fairly straightforward loop: Live Example
function findProperty(obj, path) {
var steps = path.split(/\./);
var step;
var n;
for (n = 0; n < steps.length; ++n) {
step = steps[n];
if (!(step in obj)) {
return undefined;
}
obj = obj[step];
}
return obj;
}
var a = {
user: {
joey: {
friends: {
0: {
franc: 1
}
}
}
}
};
console.log(findProperty(a, "user.joey.friends.0.franc")); // "1"
If you're trying to create an object from a string, this solution is what I currently use until I find something better (I believe it based on a namespacing method from Yahoo):
function createObject() {
var a = arguments, i, j, d, _this;
var out = {};
for (i = 0; i < a.length; i = i + 1) {
d = a[i].split('.');
out2 = out;
for (j = 0; j < d.length; j = j + 1) {
out2[d[j]] = out2[d[j]] || {};
out2 = out2[d[j]];
}
}
return out;
}
createObject('user.joey.friends.0.franc');
DEMO

Knowing position of a value under twodimensional Array

I have a SummaryData array as shown
var summaryData = [[0,100.34],[1,102.31],[2,131.08],[3,147.94],[4,172.55],[5,181.05],[6,180.08]];
My question is:
Is it possible to find out what the position of a value is?
(For example, how can I know where 147.94 is?) (I am expecting "3")
Update:
A more prototype-y way:
var result = summaryData.detect(function(item) { return item[1] === 147.94; });
alert(result[0]);
Or:
function getKey(arr, value) {
var key = null,
item;
for (var i = 0; i < arr.length && !key; i++) {
item = arr[i];
if (item[1] === value) {
key = i;
}
}
return key;
}
Usage:
var n = getKey(summaryData, 147.94); // returns 3.
At the risk of doing your homework for you...
var summaryData = [[0,100.34],[1,102.31],[2,131.08],[3,147.94],[4,172.55],[5,181.05],[6,180.08]];
function findPosition(value, dataArray) {
var a;
for (var i=0, iLen=dataArray.length; i<iLen; i++) {
a = dataArray[i];
for (var j=0, jLen=a.length; j<jLen; j++){
if (value == a[j]) {
return i + ',' + j;
}
}
}
}
alert(findPosition(131.08, summaryData)); // 2,1
The above returns the position of the first match.
Edit
I see now that you don't need to iterate over the second array, just look at the second value, so:
function findPosition(value, dataArray) {
var a;
for (var i=0, iLen=dataArray.length; i<iLen; i++) {
a = dataArray[i];
if (value == a[1]) {
return a[0];
}
}
}
alert(findPosition(131.08, summaryData)); //2
Or if the data format is always as specified and there may be thousands of values, then it may be much faster to do:
function findPosition(value, dataArray) {
var re = new RegExp('[^,],' + value);
var m = dataArray.join().match(re);
return m && m[0].replace(/,.*/,'');
// Or
// return m && m[0].split(',')[0];
}
function getPosition(candidate) {
var i = summaryData.length;
while (i) {
i -= 1;
if (summaryData[i][1] === candidate) {
return summaryData[i][0];
}
}
}

Categories

Resources