How to get index of an item from nested array - javascript

How to get the index of an item from the nested array but don't know how deep is nested
for example
arr=[a,[b,[c],[d],e],f,[g],h]

If I understand your question correctly you are trying to get the index of for example value g.
I created a little script that iterates trough the array, and possibly nested arrays, and if found the correct value returns the index.
Here is a screenshot of the array with the keys that the function getIndexOfValue returns.
var arr = [
"a",
[
"b",
[
"c"
],
[
"d"
],
"e"
],
"f",
[
"g"
],
"h"
]
function getIndexOfValue(haystack, needle) {
for(i in haystack) {
if(haystack[i] instanceof Array) {
result = getIndexOfValue(haystack[i], needle);
if(result) {
return result;
}
}
else if(haystack[i] == needle) {
return i;
}
}
return false;
}
var indexOfA = getIndexOfValue(arr, "a");
var indexOfB = getIndexOfValue(arr, "b");
var indexOfC = getIndexOfValue(arr, "c");
var indexOfD = getIndexOfValue(arr, "d");
var indexOfE = getIndexOfValue(arr, "e");
var indexOfF = getIndexOfValue(arr, "f");
var indexOfG = getIndexOfValue(arr, "g");
var indexOfH = getIndexOfValue(arr, "h");
console.log(indexOfA); //0
console.log(indexOfB); //0
console.log(indexOfC); //0
console.log(indexOfD); //0
console.log(indexOfE); //3
console.log(indexOfF); //2
console.log(indexOfG); //0
console.log(indexOfH); //4
It might still contain bugs, I created this quickly in a few minutes.

For getting the full path, you might use an iterative and recursive approach for the nested array.
The result is an array with all indices.
function findPath(array, value) {
var path = [];
array.some(function iter(p) {
return function (a, i) {
if (a === value) {
path = p.concat(i);
return true;
}
if (Array.isArray(a)) {
return a.some(iter(p.concat(i)));
};
};
}([]));
return path;
}
var array = ['a', ['b', ['c'], ['d'], 'e'], 'f', ['g'], 'h'];
console.log(findPath(array, 'a'));
console.log(findPath(array, 'b'));
console.log(findPath(array, 'c'));
console.log(findPath(array, 'd'));
console.log(findPath(array, 'e'));
console.log(findPath(array, 'f'));
console.log(findPath(array, 'g'));
console.log(findPath(array, 'h'));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

How to get a object's value by a key list

I have a obj you see bellow:
var obj = {
a: {
b:{
c:"c"
}
}
}
and I want to get value like bellow :
var t = ["a", "b", "c"] // give a key list
console.log(obj["a"]["b"]["c"]) // and get value like this.
in depth, I want to encapsulate the requirement in a function:
function get_value(obj, key_list) {
}
because the key_list is not certain, so how to realize the function?
Just use a while loop and iterate over the keys
var obj = {
a: {
b:{
c:"c"
}
}
}
var t = ["a", "b", "c"];
function get_value(obj, key_list) {
let currentReference = obj;
while (key_list.length !== 0) {
currentReference = currentReference[key_list[0]];
key_list = key_list.slice(1);
}
return currentReference;
}
console.log(get_value(obj, t));
It'd be more elegant with reduce though:
var obj = {
a: {
b:{
c:"c"
}
}
}
var t = ["a", "b", "c"];
function get_value(obj, key_list) {
return key_list.reduce((currentReference, key) => currentReference[key], obj);
}
console.log(get_value(obj, t));
Recursive solution:
function get_value(obj, key_list, i) {
if (i == undefined) {
i = 0;
}
if (i < key_list.length - 1) {
return get_value(obj[key_list[i]], key_list, i+1)
}
return obj[key_list[i]]
}

Count instances of string in a very large array and add the value to a hash value

I have a very large array of words in an array, and I want to count all of them and add the count as a value to each string.
So I for example:
words = ["a", "hello", "hello", "b", "went", "a"]
I want to convert this into:
words = [{"a" => 2}, {"b" => 1}, {"hello" => 2}, {"went" => 1}]
I have seen ways to simply count one word in a string and return its occurrences, but how might I do this at a large scale, while creating an array of hashes with the number of occurrences?
I can remove duplicate values after, I am more interested in the process of counting the values and adding the count as values in a hash.
In first turn you can create an object with the array value and number of occurrence.Then loop through it to create an array of objects
var words = ["a", "hello", "hello", "b", "went", "a"];
var rObj = {};
var finalArray = [];
words.map(function(currentValue, index) {
if (rObj.hasOwnProperty(currentValue)) {
rObj[currentValue] = rObj[currentValue] + 1;
} else {
rObj[currentValue] = 1
}
});
for (var keys in rObj) {
var obj = {};
obj[keys] = rObj[keys];
finalArray.push(obj)
};
console.log(finalArray)
You can first use reduce() to count elements and return object and then map() to return array of object values.
var words = ["a", "hello", "hello", "b", "went", "a"]
var count = words.reduce(function(r, e) {
if(!r[e]) r[e] = {[e]: 1}
else r[e][e] += 1
return r;
}, {})
var result = Object.keys(count).map(e => count[e])
console.log(result)
For a really huge array, I suggest to use either a while of a for loop and a plain check if the key with the word exist. If not assign zero to it. Later increment the property of the count object.
At last convert the object into an array with the wanted structure.
var words = ["a", "hello", "hello", "b", "went", "a"],
w,
i = words.length,
count = Object.create(null),
result;
while (i--) {
w = words[i];
if (!count[w]) {
count[w] = 0;
}
count[w]++;
}
result = Object.keys(count).map(function (k) {
var temp = {};
temp[k] = count[k];
return temp;
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Don't count repeaters by hashing. Use a while loop for smaller overhead. Assignments over calculation. You will get an answer on orders of magnitude 5 times faster. One million words randomly generated from 12 words in a 1/5th of the time.
var wordsArray = ['apple', 'beer', 'cake', 'potato', 'orange', 'monitor', 'program', 'application', 'keyboard', 'javascript', 'gaming', 'network'],
words = [];
for (i = 0; i < 1000000; i++) {
words.push(wordsArray[Math.floor(Math.random() * wordsArray.length)]);
}
function getCount(words) {
var w,
i = words.length,
hash = {};
while (i--) {
w = words[i];
if (!hash[w]) {
hash[w] = 0;
}
hash[w]++;
}
return hash
}
console.time('Obj-time');
var counts = getCount(words);
array = [];
for (let i in counts) {
var l = i.length,
val = counts[i];
array.push({
[i]: val * l
})
}
console.log(array);
console.timeEnd('Obj-time');

there is an string array A , and an string array B . I want to delete elements in A which are not in B

I think i messed somewhere, Here is my code.
var flag;
for (i = 0; i < A.length; i++)
{
flag = 0;
for (j = 0; j < B.length; j++)
{
if (A[i].indexOf(B[j]) != -1)
{
flag = 1;
}
}
if (flag == 0)
{
A.splice(i, 1);
}
}
It gives output not as per my need
Someone please Help me out
I would do the job like this;
//returns intersection of multiple arrays
Array.prototype.intersect = function(...a) {
return [this,...a].reduce((p,c) => p.filter(e => c.includes(e)));
};
var a = [0,1,2,3,4,5],
b = [4,5,6,7,8,9];
a = a.intersect(b);
console.log(a);
You could use a function which generates first an object with all characters as properties and take it as hashtable for the filtering of array1.
function deleteSome(array1, array2) {
var o = Object.create(null);
array2.forEach(function (a) {
o[a] = true;
});
return array1.filter(function (a) {
return this[a];
}, o);
}
var a = 'abcdefgh'.split(''),
b = 'banana'.split('');
console.log(deleteSome(a,b));
Technically, array "a" should have only elements which are present in array "b".
var a = [1,2,3,4];
var b = [4,5,6];
var new_a = [];
a.map(function(v,i,a){
if(b.indexOf(v) !== -1){
new_a.push(v);
}
});
console.log(new_a); //[4]
By this way i can filter as many arrays as you want.
var a = ['A', 'A', 'R', 'S', 'M', 'D', 'E']
var b = ['C', 'X', 'D', 'F']
//you can add as many arrays as you want
/*var c = ['O', 'P', 'D', 'Q']
var d = ['R', 'D', 'D', 'Z']*/
var arrays = [a,b, /*c , d */];
var result = arrays.shift().filter(function(v) {
return arrays.every(function(a) {
return a.indexOf(v) !== -1;
});
});
console.log(JSON.stringify(result));

dna pairing, pushing array inside an array

function pair(str) {
var dna = [];
var dnaarr = [];
for(var i = 0; i < str.length; i++) {
if(str[i].indexOf('G') === 0) {
var a = dna.push('C');
}
if(str[i].indexOf('C') === 0) {
var b = dna.push('G');
}
if(str[i].indexOf('A') === 0) {
var c = dna.push('T');
}
if(str[i].indexOf('T') === 0) {
var d = dna.push('A');
}
}
for(var j = 0; j < str.length; j++) {
var e = dnaarr.push(str[j]);
var f = dnaarr.push(dna[j]);
}
return dnaarr;
}
pair("ATGCG");
When I run this code, it returns
[ 'A', 'T', 'T', 'A', 'G', 'C', 'C', 'G', 'G', 'C' ]
I need it to return
[['A', 'T'], ['T', 'A'], ['G', 'C'], ['C','G'], ['G', 'C']]
Could anyone please help me with this code?
Here's a simpler version:
function pair(str)
{
// Array to hold the pairs
var dna = [];
// Loop through the string
for (var i = 0; i < str.length; i++) {
// Switch based on the current letter in the string
// Push an array to dna with the current string and it's pair
// in the case of 'G' the array would be ['G','C']
// dna would then be [['G','C']]
switch(str[i])
{
case "G":
dna.push([str[i],"C"]);
break;
case "C":
dna.push([str[i],"G"]);
break;
case "A":
dna.push([str[i],"T"]);
break;
case "T":
dna.push([str[i],"A"]);
break;
};
}
// return the array
return dna;
}
pair("ATGCG")
It was a problem with your array pushes.
function pair(str) {
var dnaarr = [];
//var dnatot = [];
for(var i = 0; i < str.length; i++) {
var dna = [];
dna.push(str[i]); //pushing current str[i]
if(str[i].indexOf('G') === 0) {
var a = dna.push('C');
}
if(str[i].indexOf('C') === 0) {
var b = dna.push('G');
}
if(str[i].indexOf('A') === 0) {
var c = dna.push('T');
}
if(str[i].indexOf('T') === 0) {
var d = dna.push('A');
}
dnaarr.push(dna); //pushing the array dna to the main array dnaarr
}
return dnaarr;
}
console.log(pair("ATGCG"));
I believe this is very easy to read and understand.
function pairElement(str) {
var pairs = { 'G': 'C', 'C': 'G', 'A': 'T', 'T': 'A' };
return str.split('').map(function(char) {
return [char, pairs[char]];
});
}
pairElement("GCG"); // [['G', 'C'], ['C', 'G'], ['G', 'C']]
EDIT: Code is simplified. On the beginning of the function we create object with possible character pairs. Using split and map array methods, we are pairing every char from str with object pairs.
I found this approach to be the most readable. Explanation in comments
function pairElement(str) {
// base pairs defined by proj requirements
var basePairs = {"A": "T", "T": "A", "C": "G", "G": "C"};
var newGeneCodeArr = [];
for (var i = 0; i < str.length; i++) {
// build individual sequence pair that fits requirements
var newGeneCode = [];
newGeneCode.push(str[i]);
newGeneCode.push(basePairs[str[i]]);
newGeneCodeArr.push(newGeneCode);
}
return newGeneCodeArr;
}
function pairElement(str) {
//convert the string into array of characters
str = str.split('');
//define a multidimensional array to hold pairing
var arr = [];
//using the for loop, we can check for each character
for(var i=0; i<str.length; i++)
{
var tmp = [];
//checking characters and adding pairs inside a tmp array
switch(str[i]){
case 'G':
tmp.push(str[i]);
tmp.push('C');
break;
case 'C':
tmp.push(str[i]);
tmp.push('G');
break;
case 'T':
tmp.push(str[i]);
tmp.push('A');
break;
case 'A':
tmp.push(str[i]);
tmp.push('T');
break;
}
//if tmp has something inside, add it to the multidimensional array
if(tmp.length > 0)
arr.push(tmp);
}
return arr;
}
pairElement("GCG");
Another, probably simpler and cleaner, version of it:
function pair(str) {
var arr = str.split(''),
newArr = [];
arr.forEach(function(e){
if (e == 'A') {
newArr.push([e, 'T']);
} else if (e == 'T') {
newArr.push([e, 'A']);
} else if (e == 'G') {
newArr.push([e, 'C']);
} else {
newArr.push([e, 'G']);
}
});
return newArr;
}
Example:
pair('GATC');
will return:
[['G','C'], ['A','T'], ['T', 'A'], ['C', 'G']]
function pair(str) {
// object of dna paring key, value
var pairing = {
"A": "T",
"T": "A",
"C": "G",
"G": "C"
},
// array to store paired object
final = [];
// make an array by .split and map that array by using the dna paring object
final = str.split('').map(function(val) {
var arr = [];
arr.push(val, pairing[val]);
return arr;
});
// return the array of paired objects
return final;
}

Retrieving Keys from JSON Array key-value pair dynamically - Javascript

I have a question that would like to seek your expertise on.
This is a JSON array that I have:
[{"A":20,"B":32,"C":27,"D":30,"E":40}]
What I would like to do is to retrieve the keys (A, B, C, D, E) from the JSON array instead of the values. I am able to retrieve the values but not the keys.
I am using this to retrieve the values dynamically:
function calculateSum(jsonArray) {
var result = 0;
for (var i = jsonArray.length - 1; i >= 0; --i)
{
var o = jsonArray[i];
A = o.A;
B = o.B;
C = o.C;
D = o.D;
E = o.E;
result = A + B + C + D + E;
return result;
}
return result;
}
Similarly, what should I do to retrieve the keys using JavaScript?
Are you using D3.js as your tag implies? Because in that case, you can just use d3.keys():
var data = [{"A":20,"B":32,"C":27,"D":30,"E":40}];
d3.keys(data[0]); // ["A", "B", "C", "D", "E"]
If you want the sum of all the values, you might be better off using d3.values() and d3.sum():
var data = [{"A":20,"B":32,"C":27,"D":30,"E":40}, {"F":50}];
// get total of all object totals
var total = d3.sum(data, function(d) {
// get total of a single object's values
return d3.sum(d3.values(d));
});
total; // 199
All of the current posted solutions have a problem. None of them check for object.hasOwnProperty(prop) while iterating over an object using a for...in loop. This might cause phantom keys to appear if properties are added to the prototype.
Quoting Douglas Crockford
Be aware that members that are added to the prototype of the object will be included in the enumeration. It is wise to program defensively by using the hasOwnProperty method to distinguish the true members of the object.
Adding a check for hasOwnProperty to maerics' excellent solution.
var getKeys = function (arr) {
var key, keys = [];
for (i = 0; i < arr.length; i++) {
for (key in arr[i]) {
if (arr[i].hasOwnProperty(key)) {
keys.push(key);
}
}
}
return keys;
};
Use for .. in:
var result = 0;
for (var i = jsonArray.length - 1; i >= 0; --i) {
var o = jsonArray[i];
for (var key in o) {
if (o.hasOwnProperty(key)) {
result += o[key];
}
}
// in your code, you return result here,
// which might not give the right result
// if the array has more than 1 element
}
return result;
var easy = {
a: 1,
b: 2,
c: 3
}
var keys = [], vals = []
for (var key in easy) {
keys.push(key)
vals.push(easy[key])
}
alert(keys+" - tha's how easy baby, it's gonna be")
alert(vals+" - tha's how easy baby, it's gonna be")
defensively
Including #Sahil's defensive method...
for (var key in easy) {
if (easy.hasOwnProperty(key)) {
keys.push(key)
vals.push(easy[key])
}
}
Try using the JavaScript for..in statement:
var getKeys = function(arr) {
var key, keys = [];
for (i=0; i<arr.length; i++) {
for (key in arr[i]) {
keys.push(key);
}
}
return keys;
};
var a = [{"A":20, "B":32, "C":27, "D":30, "E":40}, {"F":50}]
getKeys(a); // => ["A", "B", "C", "D", "E", "F"]
I think this is the simplest.
var a = [{"A":20,"B":32,"C":27,"D":30,"E":40}];
Object.keys( a[0] );
Result :
["A", "B", "C", "D", "E"]
A for-in-loop does the trick. On one object it looks like this:
var o = {
a: 5,
b: 3
};
var num = 0;
for (var key in o) {
num += o[key];
}
alert(num);
Try this. It is simple:
var a = [{"A":20,"B":32,"C":27,"D":30,"E":40}];
for(var i in a){
for(var j in a[i]){
console.log(j); // shows key
console.log(a[i][j]); // shows value
}
}
I think this should be parsed recursively like below
var getKeys = function(previousKeys,obj){
var currentKeys = Object.keys(obj);
previousKeys = previousKeys.concat(currentKeys);
for(var i=0;i<currentKeys.length;i++){
var innerObj = obj[currentKeys[i]];
if(innerObj!==null && typeof innerObj === 'object' && !Array.isArray(innerObj)){
return this.getKeys(previousKeys,innerObj);
}
}
return previousKeys;
}
usage: getKeys([],{"a":"1",n:{c:"3",e:{ f:4,g:[1,2,3]}}})
Result:
["a", "n", "c", "e", "f", "g"]
var _ = require('underscore');
var obj = [{"A":20,"B":32,"C":27,"D":30,"E":40},{"F":50}, {"G":60,"H":70},{"I":80}];
var keys = [], values = [];
_.each(obj, function(d) {
keys.push(_.keys(d));
values.push(_.values(d));
});
// Keys -> [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I' ]
console.log('Keys -> ', _.flatten(keys ));
// Values -> [ 20, 32, 27, 30, 40, 50, 60, 70, 80 ]
console.log('Values -> ', _.flatten(values));
stop reinventing the wheel !
Object.keys()
MDN

Categories

Resources