Updating array based on newer objects in another array - javascript

I have a question that is hard to describe. It's a tale of two arrays.
I have one array holding 50 objects. Per object, I want to call its specific property "IDnumber".
The second array is one that has 5 variables containing all of the mentioned 50 objects's "IDnumber" property, with each variable having a set of 10 IDnumbers: var1 is the IDnumbers of the first 10 objects, var2 is is the IDnumbers of the second set, and so on until the 50th object's ID number.
This is where it gets hard.
If I want to add in a new object in the first array, so that there'll be 51 objects, then I want to update the second array with a 6th variable, that contains all the remaining objects' IDnumbers (in this case just the 1). I want array2's length to be dependent on array1's length.
var arr1 = [], obj = {"IDNumber": "1"};
//this is an example array, all objects have the same ID here, but not in my real array
for (var i = 0; i < 51; i++) {
arr1.push(obj);
}
var var1 = [arr1[0]["IDNumber"], arr1[1]["IDNumber"], arr1[2]["IDNumber"], arr1[3]["IDNumber"], arr1[4]["IDNumber"], arr1[5]["IDNumber"], arr1[6]["IDNumber"], arr1[7]["IDNumber"], arr1[8]["IDNumber"], arr1[9]["IDNumber"]];
//the other remaining possible variables.
var arr2 = [var1, ...]; //No clue as how to take that on
How do I do that? How do I create an array that updates itself with newer possible variables like that? Each variable must have a max of 10 objects' IDnumbers.

Suppose array1 contains your array of objects. The other one is array2 containing an array of arrays, each sub array has length 10 like you stated
You can split array1 into groups of 10 and put in array2 like this
function slice10(arraysOfObject) {
var array2 = [];
var leftOver = arraysOfObject.length % 10;
var groupsOfTen = (arraysOfObject.length - leftOver)/10;
for (var i = 0; i < groupsOfTen; i++) {
array2.push([]);
for (var j = i*10; j < i*10 + 10; j++)
array2[i].push(arraysOfObject[j]["IDNumber"]);
}
//now take care of the leftover
if (leftOver > 0) {
array2.push([]);
for (var i = groupsOfTen*10; i < arraysOfObject.length; i++)
array2[array2.length-1].push(arraysOfObject[i]["IDNumber"]);
}
return array2;
}

You could create a function to deal with adding an object to the two different data structures, and use that function also for adding the first 50 objects:
function addObject(arr1, arr2, obj) {
if (arr1.length % 10 == 0) arr2.push([]);
arr1.push(obj);
arr2[arr2.length-1].push(obj.IDNumber);
}
var arr1 = [], arr2 = [];
for (var i = 0; i < 51; i++) {
addObject(arr1, arr2, {"IDNumber": i + 1000}); // some dummy ID value
}
console.log(arr2);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

Dynamically add key/value array of names into array of objects

I have an array of names. I also have an array of objects. I would like to iterate through the array of objects and also iterate through the the array of names and add the name into the objects. For example, name[0] goes into object[0], and so on.
I have this code:
this.individualSrv.GetDataById(this.org[i].userId).subscribe(data => {
this.names.push(data.fullname)
for (var x = 0; x < this.org.length; x++) {
for (var i in this.names) {
this.org[x]['name'] = this.names[i]
}
}
})
Right now, the last name in the array is added to each object in the array.
You don't need to nest 2 loops to do that. Just make sure that both arrays have the same length.
this.individualSrv.GetDataById(this.org[i].userId).subscribe(data => {
this.names.push(data.fullname)
for (var x = 0; x < this.org.length; x++) {
this.org[x]['name'] = this.names[x]
}
})

Array.length gives incorrect length

If I have an array having object as values at the indices like:
var a = [];
a[21] = {};
a[90] = {};
a[13] = {};
alert(a.length); // outputs 91
I have found a workaround to get the actual length:
function getLength(arr) {
return Object.keys(arr).length;
}
var a = [];
a[21] = {};
a[90] = {};
a[13] = {};
alert(getLength(a));
But, why does JS gives incorrect length when objects are stored at random indices? It just adds 1 to the largest index found on an array. Like in the above example, 90 was the largest index. It just adds 1 and gives 91 as output. Demonstration
That's because length gives you the next index available in the array.
DOCS
arrayLength
If the only argument passed to the Array constructor is an integer between 0 and 2^32-1 (inclusive), this returns a new JavaScript array with length set to that number.
ECMA Specifications
Because you don't have inserted any element in the other keys than 21, 90, 13, all the remaining indexes contains undefined. DEMO
To get actual number of elements in the array:
var a = [];
a[21] = {};
a[90] = {};
a[13] = {};
var len = 0;
for (var i = 0; i < a.length; i++) {
if (a[i] !== undefined) {
len++;
}
}
document.write(len);
Shorter version
var a = [];
a[21] = {};
a[90] = {};
a[13] = {};
for (var i = 0, len = 0; i < a.length; i++, a[i] !== undefined && len++);
document.write(len);
DEMO
EDIT
If the array contains large number of elements, looping to get its length is not the best choice.
As you've mentioned in the question, Object.keys(arr).length is the best solution in this case, considering that you don't have any properties added on that array. Otherwise, the length will not be what you might be expecting.(Thanks To #RobG)
The array in JavaScript is a simple zero-based structure. The array.length returns the n + 1 where n is the maximum index in an array.
That's just how it works - when you assign 90'th element and this array's length is less than 90, it expands an array to 90 and sets the 90-th element's value. All missing values are interpreted as null.
If you try the following code:
var a = [];
a[21] = {};
a[90] = {};
a[13] = {};
console.log(JSON.stringify(a));
You will get the following JSON:
[null,null,null,null,null,null,null,null,null,null,null,null,null,{},null,null,null,null,null,null,null,{},null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,{}]
Moreover, array.length is not a readonly value.
If you set a length value less than the current, then the array will be resized:
var arr = [1,2,3,4,5];
arr.length = 3;
console.log(JSON.stringify(arr));
// [1,2,3]
If you set a length value more than the current, then the array will be expanded as well:
var arr = [1,2,3];
arr.length = 5;
console.log(JSON.stringify(arr));
// [1,2,3,null,null]
In case you need to assign such values, you can use JS objects.
You can use them as associative array and assign any key-value pairs.
var a = {};
a[21] = 'a';
a[90] = 'b';
a[13] = 'c';
a['stringkey'] = 'd';
a.stringparam = 'e'; // btw, a['stringkey'] and a.stringkey is the same
console.log(JSON.stringify(a));
// returns {"13":"c","21":"a","90":"b","stringkey":"d","stringparam":"e"}
console.log(Object.keys(a).length);
// returns 5
Because that's the behavior of Array.length as described in the ECMAScript spec.
The length property of this Array object is a data property whose value is always numerically greater than the name of every deletable property whose name is an array index.
So Array.length is always the last item's index + 1.
It's because you have a[90] as largest index so the index is starting from 0 to 90 becomes 91 in length.
And where you didn't pass the values like a[80], etc. javascript will store them as hole i.e. for eg [1, , 3, , ,90] where commas are used indicates the hole in array.
If you try to access those values then you'll get undefined.

Generate random display of array elements in an array of arrays?

Ok, i have an array that contains at least two or more arrays that can contain several objects:
array[ [array[n], array[n], array[n], etc...]
my question is how to loop through and randomly pick one object from lets say array[0][1] and randomly pick another object from array[0][15] and produce no duplicates while appending each one to the page.
I have an example of what i am working on here http://jsfiddle.net/I_am_Chris/Yn5Wy/
var randObj1;
var randObj2;
var randArray;
for(i=o; i<array.length; i++){
randArray = array[i]; //get length of "nested" arrays within the array
for(n=0;n<randArray.length; n++){
randObj1 = [][].name
randObj2 = [][].name
}
}
I have tried shuffling the arrays, but that just shuffles the individual arrays, but not the outcome i need.
OK, it sounds like you want N pairs of two choices where each item in the pair is from a different array and you want no repeats.
The no repeats part is going to be efficient and run less risk of infinite looping if you create a parallel data structure that we can remove items from once chosen. This is flatly the simplest way to avoid duplicatesw without having to do a search each time. It also allow you to easily know how many choices are left in any given array in case there are no more possibilities. Here's how you could do that:
function getPairs(origData, N) {
// make copy of the data we can modify to keep track of which choices are used
var copyData = [];
for (var i = 0; i < origData.length; i++) {
copyData.push(origData[i].slice(0));
}
function getRandomValueAndRemove(skipArray) {
var randArray;
// select an array that isn't skipArray
do {
randArray = Math.floor(Math.random() * copyData.length);
} while (randArray === skipArray) ;
// select an item in that array
var randIndex = Math.floor(Math.random() * copyData[randArray].length);
var value = copyData[randArray][randIndex];
// remove that item from copyData
copyData[randArray].splice(randIndex, 1);
// if one of the arrays we selected is now empty, then remove it
if (!copyData[randArray].length) {
copyData.splice(randArray, 1);
// this array is gone so we don't have to worry about selecting it again
randArray = -1;
}
// return data and which array it is
return {value: value, whichArray: randArray};
}
// get N pairs
var pairs = [];
for (i = 0; i < N && copyData.length > 1; i++) {
var item1 = getRandomValueAndRemove();
var item2 = getRandomValueAndRemove(item1.whichArray);
pairs.push([item1.value, item2.value]);
}
// pairs contains an array of pairs
// where each item in a pair is from a different source array
// like this
// [[a, b], [c,d], [e,f]]
return pairs;
}
Working demo: http://jsfiddle.net/jfriend00/sy6XF/
If the pairs can contain any two objects, then it's simpler to do it like this.
You have some data that looks like this (array of arrays):
var origData = [[...], [...], [...]];
You can create a temporary single flat array with all the objects in it. Generate one random number to get an object. Then, remove that object from the temporary array and repeat the process (with a now shorter array). This is the simplest way of avoiding duplicates because you remove the ones you've used from the temporary array and select random choices from the remaining elements.
Here's a code example for the second option:
var origData = [[...], [...], [...]];
var flatData = [];
var item;
// put everything into flatData
for (var i = 0; i < origData.length; i++) {
flatData.push.apply(flatData, origData[i]);
}
var pairs = [];
// now select N random pairs
for (var i = 0; i < N && flatData.length > 1; i++) {
var rand = Math.floor(Math.random() * flatData.length));
var obj1 = flatData[rand];
// now remove that element from flatData so we won't pick it again
flatData.splice(rand, 1);
// get second randome value
rand = Math.floor(Math.random() * flatData.length));
var obj2 = flatData[rand];
pairs.push([obj1, obj2]);
}
// pairs contains an array of pairs
[[a, b], [c,d], [e,f]]
to generate a random number, use Math.random()
Math.random() generates a random number between 0 and 1. Then multiply by the length of the nested array to generate an index for the element you want from the nested array. Repeat the random number generation for the second index as long as it's equal to the first index. Store the results in the results array.
var results = [];
var genRandNum = function(max) {
return Math.random() * (max - 1);
}
for(var i = 0; i < array.length; i++) {
var nestedArray = array[i];
var randIndex1 = genRandNum(nestedArray.length);
results.push(nestedArray[randIndex1]);
do {
var randIndex2 = genRandNum(nestedArray.length);
} while (randIndex1 === randIndex2);
results.push(nestedArray[randIndex2]);
return results;
}
FYI, didn't test this because it wasn't clear what your test should produce.

Two for loops one ascending one descending creates two different data structures

I have an array that I am looping twice, one im looping from pointer 0 and up and the other im looping backwards.
But they produce different array layouts in console.log which i find strange .. this is what i have:
//array has a length of 3 [0,1,2]
var data = [],
data2 = [];
for(var i = 0; i < array.length-1; i++){
data[i] = {};
data[i].test = 'Hello';
}
for(var i = array.length - 1; i > 0; i--){
data2[i] = {};
data2[i].test = 'Hello';
}
console.log(data);
console.log(data2);
Now in my console log they come out different like this:
So why does the second one have a length of 3 but only 2 objects? And why does the second console.log have numbers in front of the objects unlike the first one ?
The length of an Array is simply the max(index) + 1.
When you create a "sparse" array, the intermediate indexes are still treated as existing.
console.log(JSON.stringify(data2));
// [null, {"test":"Hello"}, {"test":"Hello"}]
Even if the instance doesn't itself have them.
console.log('0' in data2);
// false
If you want a count of keys that were used, you could get the length of its Object.keys():
console.log(Object.keys(data2).length);
// 2
Possibly filtering to just indexes.
Object.indexes = function (target) {
return Object.keys(target).filter(function (key) {
return key === String(parseInt(key, 10));
});
};
console.log(Object.indexes(data2).length);
Note that these snippets expect an ES5-based engine or polyfills.
Your inner loop has this continuing condition:
i > 0
Which stops it before it gets to the data2[0] position.
And so, you're setting data2[2] and then data2[1]. data2[0] remains unset but it's still in the array (it's still the pointer position).
This is what you're looking for
for(var i = array.length - 2; i >= 0; i--){
data2[i] = {};
data2[i].test = 'Hello';
}

Search in a two dimensional array and return the array list as a array

How can I search in a two dimensional array and return the array list as a array?
var dataSet = new Array(new Array());
function searchAsset(){
dataSet.length = 0;
var fileName = document.getElementById("fileName").value;
var arr = new Array(["view_page.psd","test"],["ok_test.jpg","yes","kk"],["new_banner_2009.fla","good"],["gps-new-web.html","hot"]);
var re = new RegExp(fileName ,'i');
var res = null;
for(var i = 0;i<arr.length;i++){
var newArr = arr[i][0];
//alert(newArr+":"+newArr.match(re));
var res = newArr.match(re);
if(res != null){
dataSet.push("["+arr[i]+"]");
}
}
alert("Final --- "+dataSet);
for(var m = 0;m<dataSet.length;m++){
alert(dataSet[m]);
}
}
This:
var dataSet = new Array(new Array());
...is not a two-dimentional array. It results in an array with (initially) one element, which is a reference to another array with (initially) zero elements. The closest you'll come to a two-dimensional array in JavaScript is an array of arrays, such as:
function create2DArray(rows, columns) {
var outer, index;
outer = new Array(rows);
for (index = 0; index < rows; ++index) {
outer[index] = new Array(columns);
}
return outer;
}
Searching through such a thing is easy:
function find(thing, theArray) {
var results, col, row, subArray;
results = []; // Empty array
for (row = 0; row < theArray.length; ++row) {
subArray = theArray[row];
for (col = 0; col < subArray.length; ++col) {
value = subArray[col];
if (value == thing) { // or whatever your criterion
results.push({row: row, col: col});
}
}
}
return results;
}
That creates an array of objects, each with an col and row property, that tells you where the things in theArray are such that theArray[row][col] == thing.
Note that rather than doing theArray[row][col] every time in the loop, I grab the sub-array reference once for each row. Also note that since theoretically the sub-arrays could have different lengths, I don't assume they all have the same length.
I recommend reading up on JavaScript's arrays, which are fairly different from traditional arrays. They're really dictionaries, associative arrays, not contiguous blocks of memory indexed by an offset. When you do theArray[5], you're looking up a property called "5" on the array in exactly the way that when you say theObject['frog'] you're looking up a property "frog" on the object. (Not that implementations can't optimize that, but since JavaScript arrays are sparse, they have to be careful when doing so.)

Categories