I have an array (tlist) with keys linked with arrays:
tliste.push({"GROUP104":["321992","322052","321812","314022","0"]});
tliste.push({"GROUP108":["322011","322032","0"]});
tliste.push({"GROUP111":["322020","322021","322040","322041","313060","313072","0"]});
I now need to build a function to take the values of e.g. Group104 and Group111 and clone these into a new array:
newarrray = ["321992","322052","321812","314022","0","322020","322021","322040","322041","313060","313072","0"]
Preferably the new array should be ordered and the "0" should be removed - but that is of lower importance.
Let the groups to be extracted be grp[].
You can do something like this -
// Extract groups in grp[] from origArray[]
var extractGrps = function(grps, origArray) {
var result = [];
for(var i =0; i<grps.length; i+=1) {
var indxInOrigArray = indexOfObjectWithKey(origArray, grps[i]);
if(indxInOrigArray > 0) {
var arrLocal = origArray[indxInOrigArray].grps[i];
for(var j=0; j<arrLocal.length;j+=1)
result.push(arrLocal[j]);
}
}
return result;
}
//find Index of object in arr whose key matches the given input key
var indexOfObjectWithKey = function(arr, key) {
for(var i=0; i<arr.length; i+=1) {
if(arr[i].key) {
return i;
}
}
return -1;
}
Related
This question already has answers here:
Javascript equivalent of Python's zip function
(24 answers)
Closed 2 years ago.
I've an Object containing data that looks like this,
obj = {
Q1:['val1','val2'],
Q2:['val3','val4','val5'],
Q3:['val8']
}
I was trying to loop over keys and get and first element in each key concate each element in each array, and join them together using , (my object has more keys that this ofc)
So the output should be like
val1,val3,val8
val2,val4,
,val5,
I tried to loop over keys and getting each value but i think i'm missing something in my loop, as i can't change the key if it found element in each object
These are my trials below.
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
for (let i = 0; i < obj[key].length; i++) {
console.log(obj[key][i])//This is always looping on the same key but different element
}
}
}
while i want it to be something close to
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
console.log(obj[key][i])
}
}
My solution uses a deep copy of the object and then a recursive array manipulation via shift():
obj = {
Q1:['val1','val2'],
Q2:['val3','val4','val5'],
Q3:['val8']
}
var resObj = [];
function printByIndex(obj){
var newObj = JSON.parse(JSON.stringify(obj));
printByIndexHelper(newObj, 0);
}
function printByIndexHelper(obj, i){
var flag = false;
resObj[i] = [];
Object.keys(obj).forEach(function(key){
if(obj[key].length > 0){
resObj[i].push(obj[key].shift());
if(obj[key].length > 0){
flag = true;
}
}else{
resObj[i].push(null);
}
});
if(flag){
printByIndexHelper(obj, i+1);
}
}
printByIndex(obj);
console.log(resObj);
Maps over arrays and joins string. Math.max to get full length to iterate over. Uses flatMap to filter out unequal length array values.
obj = {
Q1:['val1','val2'],
Q2:['val3','val4','val5'],
Q3:['val8']
}
const o = Object.values(obj)
const len = Math.max(...o.map(({length})=>length))
console.log(
Array(len).fill().map((x,i)=>o.flatMap(q=>q[i]||[]).join(','))
)
check this same output as u require
obj = {
Q1:['val1','val2'],
Q2:['val3','val4','val5'],
Q3:['val8']
}
var keys = Object.keys(obj);
var stack = [];
var maxLength = getMaxLength(obj);
for(var k = 0; k < 3;k ++) {
var arr = [];
for(var i = 0; i<keys.length;i++) {
const key = keys[i];
const elements = obj[key];
if(k < elements.length) {
arr.push(elements[k]);
}
}
console.log(arr+"\n");
//stack.push(arr);
}
function getMaxLength(jsonObj) {
var max;
var jsonKeys = Object.keys(jsonObj);
for(var key of jsonKeys) {
const arr = jsonObj[key];
if (max == null || arr.length > max) {
max = arr.length;
}
}
return max;
}
I have a JavaScript array:
var data = [{abc: "vf",def: [{ a:"1", b:"3"},{a:"2",b:"4"}]}];
I want it to convert to:
[{"abc":"vf","a":"1","b":"3"},{"abc":"vf","a":"2","b":"4"}]
I have written the JavaScript code for it:
Javascript:
var push_apply = Function.apply.bind([].push);
var slice_call = Function.call.bind([].slice);
Object.defineProperty(Array.prototype, "pushArrayMembers", {
value: function() {
for (var i = 0; i < arguments.length; i++) {
var to_add = arguments[i];
for (var n = 0; n < to_add.length; n+=300) {
push_apply(this, slice_call(to_add, n, n+300));
}
}
}
});
var globalResultArr = [];
var data = [{abc: "vf",def: [{ a:"1", b:"3"},{a:"2",b:"4"}]}];
function f(){
for(var i=0;i<data.length;i++){ //Iterate Data Array
var obj = data[i];
var resultArray = [{}];
for (var key in obj) { // Iterate Object in Data Array
if (obj.hasOwnProperty(key)) {
if(Object.prototype.toString.call(obj[key]) === "[object Array]"){
var tempRes = $.extend(true, [], resultArray);
resultArray = [];
for(var k=0;k<tempRes.length;k++){
var tempResObj = tempRes[k];
for(var j=0;j<obj[key].length;j++){ // If it has array, then iterate it as well
var innerObj = obj[key][j]; //Iterate Object in inner array
for(var innerkey in innerObj){
if (innerObj.hasOwnProperty(innerkey)) {
tempResObj[innerkey] = innerObj[innerkey];
}
}
resultArray.push(tempResObj);
}
}
}else{
for(var i=0;i<resultArray.length;i++){
resultArray[i][key] = obj[key];
}
}
}
}
globalResultArr.pushArrayMembers(resultArray);
}
document.getElementById("test").innerHTML = JSON.stringify(globalResultArr);
}
f();
HTML:
<div id="test"></div>
Issue is that browser crashes when item in data array > 10000. How can i make this work? Is there any simpler approach?
JSFiddle
Here's an attempt. It assumes there is only one property in each object that is an array. It them composes an object with the remaining properties and makes a new clone with each value from the array property.
* Works as required now *
var resultArray = [],
len = data.length,
tempObj,
newObj,
targetVal,
targetKey,
composeObj,
tempJson,
key,
i, k;
for(i = 0; i < len; i++) {
tempObj = data[i];
// obj to build up
composeObj = {};
// look at all key/vals in obj in data
for(key in tempObj) {
keyObj = tempObj[key];
// is it an array?
if(Array.isArray(keyObj)) {
// save key/val for array property
targetVal = keyObj;
targetKey = key;
}
else {
// copy non-array properties to empty object
composeObj[key] = keyObj;
}
}
// json-ify the object for cloning
tempJson = JSON.stringify(composeObj);
// compose new object for each val in array property
targetVal.map(function(val) {
// clone object
newObj = JSON.parse(tempJson);
// add array values as object properties
for(k in val) {
newObj[k] = val[k];
}
// add to results
resultArray.push(newObj);
});
}
I am having following object structure
var obj = {"0":"direct","1":"indirect","2":"dir","3":"indir"};
Expected output is:
result = [["direct","indirect"],["indirect","dir"],["dir","indir"]];
What I have tried:
var result = [];
var array = [];
for(var key in obj){
if(array.length <2) {
array.push(obj[key]);
}else{
array =[];
array.push(obj[key-1]);
}
if(array.length == 2){
result.push(array);
}
}
console.log(result);
I am getting the output as follows:
result = [["direct", "indirect"], ["indirect", "indir"]]
If they're all strings that have at least one character, then you can do this:
var obj = {"0":"direct","1":"indirect","2":"dir","3":"indir"};
var result = [];
for (var i = 1; obj[i]; i++) {
result.push([obj[i-1], obj[i]]);
}
It starts at index 1 and pushes the current and previous items in an Array. It continues as long as the values are truthy, so if there's an empty string, it'll stop.
If there could be falsey values that need to be included, then you should count the properties first.
var obj = {"0":"direct","1":"indirect","2":"dir","3":"indir"};
var result = [];
var len = Object.keys(obj).length;
for (var i = 1; i < len; i++) {
result.push([obj[i-1], obj[i]]);
}
I'd like to split a string ("1,2,3") and return it as an int array so I wrote the following function:
function stringToIntArray(string) {
var split = {};
split = string.split(',');
var selected = {};
for (var i = 0; i <= split.length; i++) {
selected[i] = split[i];
}
return selected;
}
However split.length is always undefinied. Where's my mistake?
var selected = {};
doesn't build an array but an object, which has no length property.
You can fix your code by replacing it with
var selected = [];
If you want to return an array of numbers, you can change your code to
function stringToIntArray(string) {
var split = string.split(',');
var selected = [];
for (var i = 0; i < split.length; i++) {
selected.push(parseInt(split[i], 10));
}
return selected;
}
Note that I replaced <= with < in your loop.
Note also that for modern browsers, you can use the map function to make it simpler :
function stringToIntArray(string) {
return string.split(',').map(function(v){ return parseInt(v, 10) });
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Array value count javascript
I have an array which contains several duplicates, what I'm trying to achieve is to count how many duplicates each unique string has in this one array.
The array looks something like this
array = ['aa','bb','cc','aa','ss','aa','bb'];
Thus I would like to do something like this
if (xWordOccurrences >= 5) {
// do something
}
But I'm not sure how I would code this.
I was thinking, create an object with each unique string, then loop through the original array, match each string with it's object and increment it's number by 1, then loop over the object to see which words had the most duplicates...
But this seems like an over complexe way to do it.
You can use an object which has keys of the Array's values and do something like this
// count everything
function getCounts(arr) {
var i = arr.length, // var to loop over
obj = {}; // obj to store results
while (i) obj[arr[--i]] = (obj[arr[i]] || 0) + 1; // count occurrences
return obj;
}
// get specific from everything
function getCount(word, arr) {
return getCounts(arr)[word] || 0;
}
getCount('aa', ['aa','bb','cc','aa','ss','aa','bb']);
// 3
If you only ever want to get one, then it'd be more a bit more efficient to use a modified version of getCounts which looks similar to getCount, I'll call it getCount2
function getCount2(word, arr) {
var i = arr.length, // var to loop over
j = 0; // number of hits
while (i) if (arr[--i] === word) ++j; // count occurance
return j;
}
getCount2('aa', ['aa','bb','cc','aa','ss','aa','bb']);
// 3
Try this function:
var countOccurrences = function(arr,value){
var len = arr.length;
var occur = 0;
for(var i=0;i<len;i++){
if(arr[i]===value){
occur++;
}
}
return occur;
}
var count = countOccurrences(['aaa','bbb','ccc','bbb','ddd'],'bbb'); //2
If you want, you can also add this function to the Array prototype:
Array.prototype.countOccurrences = function(value){
var len = this.length;
var occur = 0;
for(var i=0;i<len;i++){
if(this[i]===value){
occur++;
}
}
return occur;
}
How about you build an object with named property?
var array = ['aa','bb','cc','aa','ss','aa','bb'];
var summary = {};
var item = '';
for ( i in array){
item = array[i];
if(summary[item]){
summary[item] += 1;
}
else{
summary[item] = 1;
}
}
console.log( summary );
summary will contain like this
{aa: 3, bb: 2, cc: 1, ss: 1}
which you could then iterate on and then sort them later on if needed.
finally to get your count, you could use this summary['aa']
<script type="text/javascript">
var array = ['aa','bb','cc','aa','ss','aa','bb'];
var myMap = {};
for(i = 0; i < array.length; i++) {
var count = myMap[array[i]];
if(count != null) {
count++;
} else {
count = 1;
}
myMap[array[i]] = count;
}
// at this point in the script, the map now contains each unique array item and a count of its entries
</script>
Hope this solves your problem
var array = ['aa','bb','cc','aa','ss','aa','bb'];
var dups = {};
for (var i = 0, l = array.length; i < l; i++ ) {
dups[array[i]] = [];
}
for (str in dups) {
for (var i = 0, l = array.length; i < l; i++ ) {
if (str === array[i]) {
dups[str].push(str);
}
}
}
for (str in dups) {
console.log(str + ' has ' + (dups[str].length - 1) + ' duplicate(s)');
}
This function may do everything you need.
function countDupStr(arr, specifier) {
var count = {}, total = 0;
arr.forEach(function (v) {
count[v] = (count[v] || 0) + 1;
});
if(typeof specifier !== 'undefined') {
return count[specifier] - 1;
}
Object.keys(count).forEach(function (k) {
total += count[k] - 1;
});
return total;
}
Each value in the array is assigned and incremented to the count object. Whether or not a specifier was passed, the function will return duplicates of that specific string or the total number of duplicates. Note that this particular technique will only work on string-coercible values inside your arrays, as Javascript can only index objects by string.
What this means is that during object assignment, the keys will normalize down to strings and cannot be relied upon for uniqueness. That is to say, this function wouldn't be able to discern the difference between duplicates of 3 and '3'. To give an example, if I were to perform:
var o = {}, t = {};
o[t] = 1;
console.log(o);
The key used in place of t would eventually be t.toString(), thus resulting in the perhaps surprising object of {'[object Object]': 1}. Just something to keep in mind when working with Javascript properties.
I saw this post about it, perhaps it can help:
http://ryanbosinger.com/blog/2011/javascript-count-duplicates-in-an-array/