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);
Related
I am trying to push numbers in an array into another array in groups of two.
If I have an array [1,4,3,2]; it should return [[1,4],[3,2]];
var arrayPairSum = function(nums) {
var len = nums.length / 2;
var arr = [];
for(var i = 0; i < len; i ++) {
var newArr = [];
newArr.push(nums[i]);
newArr.push(nums[i + 1]);
arr.push(newArr);
}
console.log(arr); //this should give me [[1,4],[3,2]];
};
arrayPairSum([1,4,3,2]);
can anyone see what I need to do to achieve this? I cannot figure it out.
You can use reduce method to achieve this. reduce method accepts a callback method provided on every item in the array.
In the other words, this method applies a function against an accumulator and each element in the array (from left to right) to reduce it to a single value.
var array=[1,4,3,2,8];
var contor=array.reduce(function(contor,item,i){
if(i%2==0)
contor.push([array[i],array[i+1]].filter(Boolean));
return contor;
},[]);
console.log(contor);
If you really want to iterate over the array, may skip every second index, so i+=2 ( as satpal already pointed out) :
var arrayPairSum = function(nums) {
var len = nums.length - 1;//if nums.length is not even, it would crash as youre doing nums[i+1], so thats why -1
var arr = [];
for (var i = 0; i < len; i += 2) {
var newArr = [];
newArr.push(nums[i]);
newArr.push(nums[i + 1]);
arr.push(newArr);
}
console.log(arr); //this should give me [[1,4],[3,2]];
};
arrayPairSum([1, 4, 3, 2]);
The upper one crops away every non pair at the end. If you want a single [value] at the end, may go with
len=nums.length
And check later before pushing
if(i+1<nums.length) newArr.push(nums[i+1]);
You were pretty close. Simply change the length to nums.length and in the loop increment i by 2.
var arrayPairSum = function(nums) {
var len = nums.length - 1;
var arr = [];
for(var i = 0; i < len; i+=2) {
var newArr = [];
newArr.push(nums[i]);
newArr.push(nums[i + 1]);
arr.push(newArr);
}
console.log(arr); //this should give me [[1,4],[3,2]];
};
arrayPairSum([1,4,3,2]);
I've looked at some other questions similar to this, but I'm getting my array in a unique way and I can't figure out for the life of my how to change it to a 2D array.
//Special function for adding arrays, just use sumArray on first array with second array in parenthesis
//==========================================
Array.prototype.sumArray = function (arr) {
var sum = this.map(function (num, idx) {
return num + arr[idx];
});
return sum;
}
var array1 = [1,2,3,4];
var array2 = [5,6,7,8];
var sum = array1.sumArray(array2);
Logger.log("sum: " + sum);
//==========================================
var calc = ss.getRangeByName( "calc" );
var target = ss.getRangeByName( "target" );
var current = ss.getRangeByName( "current" );
var left = ss.getRangeByName( "left" );
var gainedEVs = calc.getValues();
var goalEVs = target.getValues();
var oldEVs = current.getValues();
var leftEVs = left.getValues();
//Make everything ints
//==========================================
for(var i = 0; i < oldEVs.length; i++) {
Logger.log(oldEVs.length);
oldEVs[i] = parseInt(oldEVs[i]);
}
for(var i = 0; i < gainedEVs.length; i++) {
gainedEVs[i] = parseInt(gainedEVs[i]);
}
for(var i = 0; i < goalEVs.length; i++) {
goalEVs[i] = parseInt(goalEVs[i]);
}
for(var i = 0; i < leftEVs.length; i++) {
leftEVs[i] = parseInt(leftEVs[i]);
}
//==========================================
var newEVs = [[oldEVs.sumArray(gainedEVs)]];
var newLeft = [[goalEVs.subArray(newEVs)]];
//Now I try to set values and I get the error
current.setValues(newEVs);
I've tried changing the setValues to setValues([newEVs]); but that doesn't work either. Any clue on how I can get my array of newEVs to be the correct height? It has the right number of values, but those values are being stored in columns, not rows. (in this case all of my ranges are 6 rows 1 col)
Since your ranges are small, you don't have to worry too much about performance, so you can convert them from rows to columns using a loop:
var column = [];
for (var i=0; i<newEVs.length; i++){
column.push([newEVs[i]]);
}
current.setValues(column);
So i tried to apply bubble sort technique to an associative array.
What i tried is making a normal array and then applying bubble sort.
This worked , so now I'm trying to do the same for my associative array but I can't understand why it doesn't work, can someone explain and tell me how to do this?
Normal Array bubble sort code: <-- This one works
var numbers= new Array()
numbers[0] = 22;
numbers[1] = 3;
numbers[2] = 65;
numbers[3] = 75;
numbers[4] = 500;
numbers[5] = 2;
numbers[6] = 44;
for(var i=0; i<numbers.length; i++)
{
if(numbers[i] < numbers[i+1])
{
var tempGetal = numbers[i];
numbers[i] = numbers[i+1];
numbers[i+1] = tempGetal;
}
}
console.log("Smallest number from array is " + tempGetal);
associative array bubble sort code: <-- Doesn't work
var celsius= new Array()
celsius["Monday"] = 22;
celsius["Tuesday"] = 3;
celsius["Wednesday"] = 65;
celsius["Thursday"] = 75;
celsius["Friday"] = 1;
celsius["Saterday"] = 2;
celsius["Sunday"] = 44;
for(var temp in celsius)
{
if(celsius[temp] < celsius[temp+1])
{
var tempGetal = celsius[temp];
celsius[temp] = celsius[temp+1];
celsius[temp+1] = tempGetal;
}
}
console.log("Smallest number from this array is " + tempGetal[temp]);
Can anyone tell me if the method I'm trying to apply is possible?
Thanks in advance!
There are several reasons why your attempt didn't work, but there is a fundamental flaw in your assumption: the order of properties in an object is undefined, so you should not try to rearrange them.
There's really no reason to use sorting for this. Just go through the object once and find the lowest value:
var min = Infinity;
for(var day in celsius) {
if(celsius[day] < min) {
min = celsius[day];
}
}
console.log(min);
A fancier solution:
var celsius = [];
celsius["Monday"] = 22;
celsius["Tuesday"] = 3;
celsius["Wednesday"] = 65;
celsius["Thursday"] = 75;
celsius["Friday"] = 1;
celsius["Saterday"] = 2;
celsius["Sunday"] = 44;
var min = Object
.keys(celsius)
.map(function(key) {
return celsius[key];
})
.reduce(function(last, next) {
return last < next ? last : next;
}, Infinity);
console.log(min);
Other problems with your approach:
Javascript does not have associative arrays. You should generally not create an array and assign named properties to it (that's what objects are for).
If you iterate through an object with for(var temp in celsius), temp will be the property names, not the temperatures or numerical indices.
With the previous bullet in mind, if temp has the value "Monday", then celsius[temp + 1] = tempGetal will assign tempGetal to the property Monday1.
For the record, your bubble sort doesn't work correctly because you should keep sorting until nothing moves, e.g.
// Sort an array of Numbers
function bubbleSort(arr) {
var oneMoved, // flag if one moved
i, // counter
t; // temp variable
do {
// reset flag
oneMoved = false;
// reset counter
i = arr.length - 1;
while (i--) {
// If array members are out of sequence, swap
if (arr[i] > arr[i+1]) {
t = arr[i];
arr[i] = arr[i+1]
arr[i+1] = t;
// Remember that one moved
oneMoved = true;
}
}
// Keep going as long as one moved
} while (oneMoved)
// Not necessary as array sorted in place, but means function
// can be chained
return arr;
}
// Quick test
var arr = [0, 3, 6, -2, 3];
console.log(bubbleSort(arr)); // [-2, 0, 3, 3, 6]
I have a nice riddle that I would like to see solved. There might be a better way of doing this and i am open for idea's.
I am trying to write an undo function for a canvas drawing app.
I have the following object, within it an array with their own objects with three properties.
var allDamages= {};
allDamages['scratch'] = [];
allDamages['scratch'].push({"x":4,"y":6,"index":1});
allDamages['scratch'].push({"x":3,"y":3,"index":2});
allDamages['scratch'].push({"x":9,"y":9,"index":3});
allDamages['scratch'].push({"x":19,"y":39,"index":4});
allDamages['dent'] = [];
allDamages['dent'].push({"x":59,"y":69,"index":5});
allDamages['dent'].push({"x":59,"y":69,"index":9});
allDamages['dent'].push({"x":39,"y":19,"index":6});
allDamages['rip'] = [];
allDamages['rip'].push({"x":20,"y":22,"index":7});
allDamages['rip'].push({"x":100,"y":56,"index":8});
I want to remove the last entry from this array. I want to do this by the property 'index'.
So I need to somehow find the entry which has the highest value of the property 'index' and then remove it from the array. What is the best way in doing this?
Greetings,
Robert
allDamages.scratch.length -1 returns the last index for that array.
Edit:
allDamages.scratch.slice(-1).pop() returns the last array item.
And if you just want to remove the last item in your array you should (like Givi said) use the pop() method on a sorted array like so:
allDamages['scratch'].pop()
Edit2:
Because the question wasn't clear for me. This is my final shot at the problem.
var allDamagesInOneArray = [];
for(array in allDamages){
allDamagesInOneArray.concat(array);//Assuming every key is an array
}
allDamagesInOneArray.sort(function(a,b){
return a.index - b.index;
});
var lastObj = allDamagesInOneArray.slice(-1).pop(); //element with latest index
I think you should create an object that save three your properties. After that you create a stack for undo. Like this:
function yourObject(x,y,index){
this.x = x; this.y = y; this.index = index;
}
var yourStack = new Array();
yourStack.push(new yourObject(4, 6, 1));
If the highest index in an array is always the last element of the array:
allDamages.scratch = allDamages.scratch.slice(0, allDamages.scratch.length - 1);
This removes the last element of the array
If index is not incrementing or if you always want to remove the latest index, no matter in which of the damages arrays it is (as I'd guess) you can use this function:
var undo = function(input){
var max= 0;
var undoType = "";
var undoIndex = 0;
for( var type in input ) {
// type: string
var locations = input[type];
// locations: array
// find the location of the heighest index property.
for( var i = 0; i < locations.length; i++ ) {
if( locations[i]["index"] > max) {
max = locations[i]["index"] ;
undoType = type;
undoIndex = index;
}
}
}
var output = input[type].splice(undoIndex, 1);
return output;
}
This should remove the element with the largest "index" property from your damage array.
First off, store a counter for highest index property found in the objects, and the index of that object within the scratch array.
var highestIndex = -Infinity;
var indexInArray
Then if you're using jQuery:
$.each( allDamages.scratch, function highestIndex( index, object ){
if( object.index > highestIndex ){
highestIndex = object.index;
indexInArray = index;
}
} );
Or, if not:
for( var indexCounter = 0, indexCounter < allDamages.scratch, indexCounter++ ){
if( allDamanges.scratch[ indexCounter ].index > highestIndex ){
highestIndex = allDamages.scratch[ indexCounter ].index;
indexInArray = indexCounter;
}
};
Try:
var allDamages= {};
allDamages['scratch'] = [];
allDamages['scratch'].push({"x":4,"y":6,"index":1});
allDamages['scratch'].push({"x":3,"y":3,"index":2});
allDamages['scratch'].push({"x":9,"y":9,"index":3});
allDamages['scratch'].push({"x":19,"y":39,"index":4});
allDamages['dent'] = [];
allDamages['dent'].push({"x":59,"y":69,"index":5});
allDamages['dent'].push({"x":59,"y":69,"index":9});
allDamages['dent'].push({"x":39,"y":19,"index":6});
allDamages['rip'] = [];
allDamages['rip'].push({"x":20,"y":22,"index":7});
allDamages['rip'].push({"x":100,"y":56,"index":8});
var index;
var cnt = 0;
var val;
$.each(allDamages,function(k,v){
if(cnt == 0){
index = highest(v); //get highest value from each object of allDamages
val = k;
}
else{
if(highest(v) > index){
index = highest(v);
val = k;
}
}
cnt++;
});
console.log("highest : "+index+": "+val);
var len = allDamages[val].length;
for(var i=0;i<len;i++){
if(allDamages[val][i].index == index){
allDamages[val].splice(i,1); //remove object having highest value
break;
}
}
console.log(allDamages);
function highest(ary) {
var high = ary[0].index;
var len = ary.length;
if(len > 0){
for(var i=0;i<len;i++){
if(ary[i].index > high){
high = ary[i].index;
}
}
}
return high;
}
DEMO here.
I've simplified my array to:
allDamages.push({"x":39,"y":19,"index":6,"type":'dent'});
That way i can use .pop() function in a normal way.
Thank you all for the quick response!!!
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/