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

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.

Related

Combinations of specific elements in array

Let's say that I'm doing this because of my homework. I would like to develop some kind of schedule for the week to come (array of 6-7 elements - output result). But I have one problem. I need to figure it out how one element be positioned in the array and also his frequency must be exactly what user input is. Elements must be positioned at different index in the array.
I'm having that kind of input from user (just an example);
var arrayOfElements = ["el1","el2","el3"];
var el1Frequency = 3;
var el2Frequency = 2;
var el3Frequency = 1;
//output array of schedule (this is just an example)
var finaloutPutArray = ["el1","el2","el3","el1","el2","el1"];
Index of elements el1 is 0, 3 and 5, basically, I don't want elements to be repeated like this;
["el1","el1","el2","el3"...];
["el2","el1","el1","el3"];
Can you please give me some ideas on how to solve this problem.
I started like this;
var finalSchedule = [];
var totalDaysPerWeek = 6;
for(var i =0; i < totalDaysPerWeek; i++) {
...
}
This is one pattern, check my working snippet:
var arrayOfElements = ["el1","el2","el3"];
var obj = { el1: 3,
el2: 2,
el3: 1};
// First determine the max recurring of an element, this will be the number of cycles fo your loop
// Check key values
var arr = Object.keys(obj).map(function ( key ) { return obj[key]; });
// Get max value
var max = Math.max.apply( null, arr );
var finalArray = [];
// Iterate from 0 to max val
for(i = 0; i < max; i += 1){
// Iterate on array of elements
for(k = 0; k < arrayOfElements.length; k += 1) {
// If config of recurring
if( obj[arrayOfElements[k]] >= i+1 ) {
// Push into array
finalArray.push(arrayOfElements[k]);
}
}
}
console.log(finalArray);

Trying to create an array of duplicate values from another array, why doesn't my code work?

I am working on this piece of code here where the goal is to create an array of all the values that are duplicated from another array. The resulting array I'd like to have should only enter the duplicated values from the first array once. The catch is I can't use any array functions or methods. This is what I have so far:
var numbers = [8,24,20,5,13,3,1,12,11,24,8,24,20,4,5,23,24,23,21,2,19,3,21,2,14,17,21,5,7,10,20,11,0,5,18,2,13,11,14,3,20,1,23,6,21,10,14,0,15,20];
var results = [];
var tempArr = [];
for (var i = 0; i <= numbers.length; i++) {
if (tempArr[numbers[i]] === undefined) {
tempArr[numbers[i]] = 1;
} else if (results[numbers[i]] === undefined) {
results.push(numbers[i]);
}
}
console.log(tempArr);
console.log(results);
I am getting closer to me desired output… but for some reason the results array continues to contain multiple entries of the values that are duplicated in the numbers array. Where am I going wrong here?
You're basically abusing an array as an object. Try using an object instead to log your values (and give said object a name that represents what it holds), it'll greatly simplify your code:
var numbers = [8,24,20,5,13,3,1,12,11,24,8,24,20,4,5,23,24,23,21,2,19,3,21,2,14,17,21,5,7,10,20,11,0,5,18,2,13,11,14,3,20,1,23,6,21,10,14,0,15,20];
var results = [];
var seenValues = {};
for (var i = 0; i < numbers.length; i++) {
const number = numbers[i];
seenValues[number] = 1 + (seenValues[number] || 0);
// check to see if it's been seen exactly once before,
// so that the duplicated value is only added once:
if (seenValues[number] === 2) results[results.length] = number;
}
//console.log(seenValues);
console.log(results);

Combining 2D Array with Key-Value Array

I have an array where each row is an array that has 2 values, S/N and Description.
array1 = [["xx9","Big Car"],["xx1","Small Car"],["xx9","Big Car"],["xx9"," Big Car"]];
As you can see there are duplicates. So I wrote code that creates a count array that holds the key-value pairs and counts each item. Length of count is 1.
count = [xx1: 1
xx9: 3]
So now I want to combine the two arrays into one new one that includes the quantity, in this example the final output would be as shown below. Note that I have to also remove the duplicates in array1. Order doesn't matter.
final_array = [["1","xx1","Small Car"],["3",xx9","Big Car"]];
Here is my JS code so far but basically the .forEach loops won't work over the count array. Can anyone help me so that this code works on the key-value array.
JS/Jquery:
//Pull the Cart Data & Orangize
var savedList = JSON.parse(localStorage.getItem("partList"));
console.log(savedList);
determineQuantity(savedList); //Count quantity of each item
//Count the Quantity of each item in saved list & create key-value pairs
function determineQuantity(savedList){
var newList = [];
var count = [];
for (var i=0, j = savedList.length; i<j; i++){
count[savedList[i][0]] = (count[savedList[i][0]] || 0) + 1;
};
console.log(count);
//Combine Quantity Array with SavedList Array
count.forEach(function(item,index){
console.log("index = " + index + " item = " + item);
savedList.forEach(function(row){
if ($.inArray(item,row == 0)){ //if found in this row at index 0
var new_part = [count[index],row[0],row[1]];
console.log("new_part = " + new_part);
newList.push(new_part);
};
});
});
console.log(newList);
};
how about this.
var test = function(){
var array = [["xx9","Big Car"],["xx1","Small Car"],["xx9","Big Car"],["xx9"," Big Car"]];
var count = {xx1: 1, xx9: 3};
var map = {};
array.forEach(function(item){map[item[0]] = item[1]});
var newArray = [];
for(var key in count){
if(!map[key])
continue;
newArray.push([count[key], key, map[key]]);
}
console.log(newArray);
}
first of all, you count is a object, not a array. then we dont need forEach

Updating array based on newer objects in another array

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; }

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