Why is this happening with javascript objects - javascript

I am working on a function to map a string that has been split into an array
function arrayDups(a) // a: array to search: as in string split into array.
{
var unique = {}
var dups = [];
var seen = false;
var bypass = {};
for(var i = 0; i < a.length; i++)
{
if(bypass[a[i]] == 'undefined')
{
unique[a[i]] = i+',';
bypass[a[i]] = false;
}
for(var k = i; k < a.length; k++)
{
// so the same char later will not produce duplicate records.
if(unique[a[k]] != 'undefined' && bypass[a[k]] != 'undefined' && !bypass[a[k]])
{
unique[a[k]] += k+',';
if(k == a.length - 1)
{
bypass[a[i]] = true
}
}
}
}
for(var x in unique)
{
dups[dups.length] = x+':'+unique[x]
}
return dups;
}
this is colled in the following context
var testCase = ('disproportionate').split('');
window.onload = function()
{
var test = document.getElementById('res')
test.childNodes[0].data = arrayDups(testCase).join("\n")
}
which produces the following output
d:undefined0,
i:undefined1,10,1,10,
s:undefined2,2,2,
p:undefined3,6,3,6,3,6,3,6,
r:undefined4,8,4,8,4,8,4,8,4,8,
o:undefined5,7,11,5,7,11,5,7,11,5,7,11,5,7,11,5,7,11,
t:undefined9,14,9,14,9,14,9,14,9,14,9,14,9,14,9,14,9,14,9,14,
n:undefined12,12,12,12,12,12,12,12,12,12,12,12,12,
a:undefined13,13,13,13,13,13,13,13,13,13,13,13,13,13,
e:undefined15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
The questions:
where is undefined coming from
and why are the index positions being duplicated when for each iteration of i
k begins at the current i value and should be looking ahead to find index values of duplicate chars
I wouldn't want to answer my own question so I am adding to the original post via edits
Here is what I came up with
function arrayDups(a) // a: array to search: as in string split into array.
{
var unique = {}
var dups = [];
var seen = false;
var bypass = {};
for(var i = 0; i < a.length; i++)
{
if(!bypass.propertyIsEnumerable(a[i]))
{
unique[a[i]] = i+',';
bypass[a[i]] = 'false';
continue;
}
if(bypass.propertyIsEnumerable(a[i]) && bypass[a[i]] == 'false')
{
for(var k = i; k < a.length; k++)
{
// for every instance of a[i] == a[k] unique[a[k]] will be defined
if(a[i] == a[k] && unique.propertyIsEnumerable(a[k]))
{
unique[a[k]] += k+',';
}
if(k == a.length - 1)
{
bypass[a[i]] = 'true'
continue;
}
}
}
}
for(var x in unique)
{
dups[dups.length] = x+':'+unique[x]
}
return dups;
}
And this is the output
d:0,
i:1,10,
s:2,
p:3,6,
r:4,8,
o:5,7,11,
t:9,14,
n:12,
a:13,
e:15,
so now all I have to do is strip the railing ','

Related

Javascript - Permutations remove the duplicates elements

that is found here in stack but i want somes changes.
function perms(data) {
if (!(data instanceof Array)) {
throw new TypeError("input data must be an Array");
}
data = data.slice(); // make a copy
var permutations = [],
stack = [];
function doPerm() {
if (data.length == 0) {
permutations.push(stack.slice());
}
for (var i = 0; i < data.length; i++) {
var x = data.splice(i,1);
stack.push(x);
doPerm();
stack.pop();
data.splice(i, 0, x);
}
}
doPerm();
return permutations;
}
var input = "552".split('');
var result = perms(input);
for (var i = 0; i < result.length; i++) {
result[i] = result[i].join('-');
}
The result of that is :
5-5-2
5-2-5
5-5-2
5-2-5
2-5-5
2-5-5
but , are 3 elements duplicates the result must be :
5-5-2
5-2-5
2-5-5
how can i fix that issue .
Basically, you have one issue,
var x = data.splice(i, 1)[0];
// ^^^ is missing
because you get an array with splicing. The result is a deep nested array with
data.splice(i, 0, x);
This inserts the array later on position i.
For preventing duplicates, you need a check, if the actual value is already inserted in the result set with
permutations.some(function (a) {
return a.every(function (b, j) {
return stack[j] === b;
});
}) || permutations.push(stack.slice());
which test the arrays and if no match, the push is performed.
function perms(data) {
if (!(data instanceof Array)) {
throw new TypeError("input data must be an Array");
}
data = data.slice(); // make a copy
var permutations = [],
stack = [],
hash = Object.create(null);
function doPerm() {
if (data.length == 0) {
permutations.some(function (a) {
return a.every(function (b, j) {
return stack[j] === b;
});
}) || permutations.push(stack.slice());
return;
}
for (var i = 0; i < data.length; i++) {
var x = data.splice(i, 1)[0];
stack.push(x);
doPerm();
stack.pop();
data.splice(i, 0, x);
}
}
doPerm();
return permutations;
}
var input = "552".split('');
var result = perms(input);
for (var i = 0; i < result.length; i++) {
result[i] = result[i].join('-');
}
console.log(result);
Check if array array is present within resulting array before calling .push() using Array.prototype.some(), Array.prototype.join()
function p(a, b, res) {
var b = b || [],
res = res || [],
len = a.length;
if (!len) {
// check if `res` contains `b.join("")`
if (!res.length
|| !res.some(function(n) {
return n.join("") === b.join("")
}))
res.push(b)
} else {
for (var i = 0
; i < len; p(a.slice(0, i).concat(a.slice(i + 1, len))
, b.concat(a[i]), res)
, i++);
}
return res
}
var result = p("552".split(""));
result = result.map(function(res) {
return res.join("-")
});
console.log(result);

How to get all possible combinations of elements in an array including order and lengths

function getAllCombinations(arr) {
var f = function(arr) {
var result = [];
var temp = [];
for (var i = 0; i < arr.length; i++) {
temp = [];
temp.push(arr[i]);
result.push(temp);
for (var j = 0; j < arr.length; j++) {
if (j != i) {
temp = [];
temp.push(arr[i]);
temp.push(arr[j]);
result.push(temp);
for (var k = 0; k < arr.length; k++) {
if (k != i && k != j) {
temp = [];
temp.push(arr[i]);
temp.push(arr[j]);
temp.push(arr[k]);
result.push(temp);
for (var l = 0; l < arr.length; l++) {
if (l != i && l != j && l != k) {
temp = [];
temp.push(arr[i]);
temp.push(arr[j]);
temp.push(arr[k]);
temp.push(arr[l]);
result.push(temp);
}
}
}
}
}
}
}
return result;
}
return f(arr);
}
//call this function
console.log(getAllCombinations(["a", "b", "c", "d"]));
[["a"],["a","b"],["a","b","c"],["a","b","c","d"],["a","b","d"],["a","b","d","c"],["a","c"],["a","c","b"],["a","c","b","d"],["a","c","d"],["a","c","d","b"],["a","d"],["a","d","b"],["a","d","b","c"],["a","d","c"],["a","d","c","b"],["b"],["b","a"],["b","a","c"],["b","a","c","d"],["b","a","d"],["b","a","d","c"],["b","c"],["b","c","a"],["b","c","a","d"],["b","c","d"],["b","c","d","a"],["b","d"],["b","d","a"],["b","d","a","c"],["b","d","c"],["b","d","c","a"],["c"],["c","a"],["c","a","b"],["c","a","b","d"],["c","a","d"],["c","a","d","b"],["c","b"],["c","b","a"],["c","b","a","d"],["c","b","d"],["c","b","d","a"],["c","d"],["c","d","a"],["c","d","a","b"],["c","d","b"],["c","d","b","a"],["d"],["d","a"],["d","a","b"],["d","a","b","c"],["d","a","c"],["d","a","c","b"],["d","b"],["d","b","a"],["d","b","a","c"],["d","b","c"],["d","b","c","a"],["d","c"],["d","c","a"],["d","c","a","b"],["d","c","b"],["d","c","b","a"]]
A total of 64 combinations for a 4 length array.
The function works fine but I need to make this function recursive. The for loops have to be nested based on the length of the array and the push also increased per nested loop.
Really appreciate some advice.
Finally made it recursive !!
Tried to work down on the the original code posted above moving each loop functionality into simple functions.
function getAllCombinations(inputArray) {
var resultArray = [];
var combine = function() {
for (var i in inputArray) {
var temp = [];
var tempResult = [];
for (var j in arguments) {
tempResult.push(inputArray[arguments[j]]);
if (arguments[j] == i) {
temp = false;
} else if (temp) {
temp.push(arguments[j]);
}
}
if (temp) {
temp.push(i);
combine.apply(null, temp);
}
}
if (tempResult.length > 0) {
resultArray.push(tempResult);
}
return resultArray;
};
return combine();
}
See the older version here.
Result produces 64 unique combinations for a 4 dimensional array
console.log(getAllCombinations(["a", "b", "c", "d"]));
[["a","b","c","d"],["a","b","c"],["a","b","d","c"],["a","b","d"],["a","b"],["a","c","b","d"],["a","c","b"],["a","c","d","b"],["a","c","d"],["a","c"],["a","d","b","c"],["a","d","b"],["a","d","c","b"],["a","d","c"],["a","d"],["a"],["b","a","c","d"],["b","a","c"],["b","a","d","c"],["b","a","d"],["b","a"],["b","c","a","d"],["b","c","a"],["b","c","d","a"],["b","c","d"],["b","c"],["b","d","a","c"],["b","d","a"],["b","d","c","a"],["b","d","c"],["b","d"],["b"],["c","a","b","d"],["c","a","b"],["c","a","d","b"],["c","a","d"],["c","a"],["c","b","a","d"],["c","b","a"],["c","b","d","a"],["c","b","d"],["c","b"],["c","d","a","b"],["c","d","a"],["c","d","b","a"],["c","d","b"],["c","d"],["c"],["d","a","b","c"],["d","a","b"],["d","a","c","b"],["d","a","c"],["d","a"],["d","b","a","c"],["d","b","a"],["d","b","c","a"],["d","b","c"],["d","b"],["d","c","a","b"],["d","c","a"],["d","c","b","a"],["d","c","b"],["d","c"],["d"]]
Here is my solution using a subroutine, and closures. Also slice is very useful here.
If you found this helpful, or if you think other people will find this helpful, don't be afraid to upvote.
function getMyCombinations(coll) {
const result = [];
(function search(currentPerm, letters) {
if (letters.length === 0) return result.push(currentPerm);
let trimArray = letters.slice(1);
letters.forEach(letter => search(currentPerm + letter, trimArray));
})('', coll)
return result;
}
console.log(getMyCombinations(["a", "b", "c", "d"]));
I have refactored my original answer to better align with the users request.
function findPerm(array, currentPerm = '', result =[]) {
if (array.length === 0) return result;
let trimArray = array.slice(1);
array.forEach(v => {
let copy = [...result];
let perm = (currentPerm + v).split('');
let res = copy.push(perm);
result = findPerm(trimArray, currentPerm + v, copy);
});
return result;
};
console.log(findPerm(['a', 'b', 'c', 'd']));
An alternative solution, seems getting the desired output :)
console.log(JSON.stringify(getMyCombinations(["a", "b", "c", "d"])))
function getMyCombinations(arry) {
var len = arry.length;
var tempArray = [];
var result = []
var tempCount = 1;
var createCombinations = function(count){
var singleLevelArray = [];
arry.forEach(function(item){
if(count){//1
if(count > 1){
for(var j = 0; j < tempArray.length; j++){
if(tempArray[j].indexOf(item) === -1){
var x = tempArray[j].slice();
x.push(item);
singleLevelArray.push(x);
result.push(x);
}
}
} else {
for(var k = 0; k < len; k++){
if(item.indexOf(arry[k]) === -1){
tempArray.push([item, arry[k]]);
result.push([item, arry[k]]);
}
}
}
} else {
result.push([item]);
}
})
if(singleLevelArray.length){
tempArray = []
tempArray = singleLevelArray;
}
if(tempCount < len){
createCombinations(tempCount++);
}
return result;
}
return createCombinations()
}

javascript array - increment value at given key

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.

Get multiple character positions in array?

I want to get position of dots and commas in an array.
w.wer,ads,
should give something like:
[0] > 1
[1] > 5
[2] > 9
How can this be done with javascript?
function getPositions(regex, str) {
var counts = [], m;
while (m = regex.exec(str)) {
counts.push(regex.lastIndex - m[0].length);
}
return counts;
}
// Usage:
getPositions(/[,.]/g, 'w.wer,ads,'); // => [1,5,9]
Try the following
var getAllIndexesOf = function(str, toFind) {
var all = [];
for (var i = 0; i < str.length; i++) {
if (toFind.indexOf(str[i]) >= 0) {
all.push(i);
}
}
return all;
}
var result = getAllIndexsOf("w.wer,ads,", [".", ","]);
Option 1
Simply loop through each character in the string:
var myString = "w.wer,ads,";
var matchedIndexes = [];
for (var i = 0; i < myString.length; i++) {
if (myString[i] == "," || myString[i] == ".") {
matchedIndexes.push(i);
}
}
Here's a working fiddle.
Option 2
If you wanted to get a bit fancier with it, you could create an object that stores the position and the character at that position:
var myString = "w.wer,ads,";
var matchedIndexes = [];
for (var i = 0; i < myString.length; i++) {
if (myString[i] == "," || myString[i] == ".") {
matchedIndexes.push(new myMatch(myString[i], i));
}
}
function myMatch(position, character) {
this.position = position;
this.character = character;
}
Result:
​
Here's a working fiddle.
function dotsAndCommas(s) {
var rv = [];
for (var i = 0; i < s.length; ++i) {
if (s[i] === '.' || s[i] === ',') rv.push(i);
}
return rv;
}
Basically, just do it. There's no shortcut way I can think of to do it with a regex.
Probably not ideal, but as a thought experiment, here is a way to do it with built-in javascript functions (no explicit loops):
var pos = mystr.split(/[,.]/).slice(0,-1).map(function(val, i, a) { return a.slice(0, i+1).join('').length+i; });
Demo: http://jsfiddle.net/jtbowden/hHSB2/
To get rid of the nested .slice() which is O(n^2):
var pos = mystr.split(/[,.]/).slice(0,-1).map(function(val, i, a) { return a[i] = val.length+(a[i-1]||-1)+1; });
Demo: http://jsfiddle.net/jtbowden/hHSB2/1/
And, yes, it is still ugly and pointless.
Yet another almost one-liner:
var q = [];
[].forEach.call('w.wer,ads,', function(v, i) { /[,.]/.test(v) ? q.push(i) : 0 } );
// q == [1,5,9]
I would loop through the string and check each character like so:
var s = "w.wer,ads,";
var arr = new Array();
for( var i = 0; i < s.length; i++ ) {
if( s.charAt(i) == "." || s.charAt(i) == "," )
arr.push(i);
}
for( var i = 0; i < arr.length; i++ ) {
document.write( arr[i] );
}
Since there're 5 solutions already, I'll write my almost one-liner.
function dotsAndCommasPositions(str) {
var i = -1;
return str.split(/[.,]/).slice(0, -1).map(function(s){ return i += s.length + 1; });
};
You can create a function that loops through all the characters and saves the index of . and ,.
​function getPositionsOfDotsCommas(str) {
var result = [];
for (var i = 0; i < str.length; i++) {
if (str[i] === '.' || str[i] === ',') {
result.push(i);
}
}
return result;
}​

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