Javascript: Defining an array with shortcuts - javascript

I don't really know how to ask this and maybe that is why I can't properly find the answer to this problem.
So I have a very long list of numbers and I intend to put them in an array.
154,153,152,148,145,133,132,131,130,...,6,5,4,1 (You get the idea.)
The problem is that I'm lazy and don't want to type out all the numbers out into this "initial" array. (Notice that there are sequential strings of numbers in the list.)
I thought I could do something like this:
var array = [154:152,148,133:130,...,6:4,1];
Which would yield something like this for array:
[154,153,152,148,133,132,131,130,...,6,5,4,1]
I know I can do a loop to fill these in. But the tricky parts are the "breaks" in the sequence.
Any help or obvious solution that I missed would be appreciated.
(This is for some code in google spreadsheets, which uses javascript as a basis.)

No, you can't do that natively.
You could however write a simple helper function which does it for you.
function createRange(arr) {
var result = [], //The resulting array
range;
for (var i = 0; i < arr.length; i++) {//Iterate over the array
if (Array.isArray(arr[i])) { //If we find another array
range = arr [i];
for (var j=range [0]; j <= range [1]; j++) {//increase its first element until it's equal the second
result.push(j); //add the number to the resulting array
}
} else { //If it's a number
result.push(arr[i]); //put it in the resulting array
}
}
return result; //return the array containing the range
}
createRange ([[1,5],10,[15,20]]) //[1, 2, 3, 4, 5, 10, 15, 16, 17, 18, 19, 20]
Heres a Fiddle as well

what do you think about this?
var a = ['154:152','148','133:130','6:4','1'];
var array = [];
for (i = 0; i < a.length; i++)
{
var b = a[i];
b = b.split(':');
if (b.length == 2)
{
for (var j = b[0]; j > b[1]-1; j--)
{
array[array.length] = j;
document.write(j);
}
}
else
{
array[array.length] = b[0];
document.write(b[0]);
}
}

Related

An array of primes generated from a given array (JavaScript)

I am trying to take a given array and iterate through it to create a new array containing only the numbers that are prime from the given array.
What I'm not sure of is the syntax for doing so - I know this is butchered and wrong, but I'm not sure how to fix it? Or if I'm even going about it the right way.
var myArray = isPrime([1,5,17,25,30])
console.log(myArray)
function isPrime(array){
var primes = [];
for(var i = 0; i < array.length; i++){
if(array[i] /= 1 || array[i] / 1 == array[i]){
primes.push([i]);
}
}
return primes;
}
A simple way to do it is creating a isElementPrime(number) function that tells if the number is prime or not (find an implementation here), and loop through it!
function isPrime(array){
var primes = [];
for(var i = 0; i < array.length; i++){
if(isElementPrime(array[i]){
primes.push(array[i]);
}
}
return primes;
}
The idea is to divide the number by every number smaller than it and greater than 1 and see if there is a remainder.
Using filter you can apply this to all elements in the array;
See example:
function isPrime(element) {
for(var i = 2; i < element; i++) {
if(element % i === 0) {
return false;
}
}
return element !== 1;
}
var array = [1, 5, 17, 25, 30];
var primes = array.filter(isPrime);
console.log("array: " + array);
console.log("primes: " + primes);

Javascript computing permutations - why is my code returning unwanted solution when I don't make a copy of the array?

Below is code for a function that returns all permutations of a given array.
function getAllPerms(s) {
var perms = [];
if (s.length === 1) {
perms.push(s);
} else {
for (var i = 0; i < s.length; i++) {
var sub = s.slice(0);
sub.splice(i, 1);
var sp = getAllPerms(sub);
for (var o = 0; o < sp.length; o++) {
sp[o].unshift(s[i]);
perms.push(sp[o]);
}
}
}
return perms;
}
console.log(getAllPerms([1,2])); // result is [[1, 2], [2, 1]]
however if i don't make a copy of the array and splice the original array I don't get the same output, and I have been racking my brain to understand why? To me, it seems as though it should work either way. Below is the code with changes to the original array.
function getAllPerms(s) {
var perms = [];
var len = s.length
if (s.length === 1) {
perms.push(s);
} else {
for (var i = 0; i < len; i++) {
var digit = s[i];
s.splice(i, 1);
var sp = getAllPerms(s);
for (var o = 0; o < sp.length; o++) {
sp[o].unshift(digit);
perms.push(sp[o]);
}
}
}
return perms;
}
console.log(getAllPerms([1,2])); // result is [[2, 1], [2, 1]]
For the first set of code I get the correct result,[[1, 2], [2, 1]], but for the second bit of code I get something strange, [[2, 1], [2, 1]]. Cannot for the life of me figure out what is going on.
When you run the code that changes the original array, you're actually modifying the input array sto be first [1,2] then [2,1], and your return array is just the original array s multiple times, so modifying s to become the second element also modifies it as the first element.
You can see the effect more simply by running the following:
var x = [1,2]
var p = []
p.push(x)
x[0] = 2
x[1] = 1
p.push(x)
Observe how x and p change after each line.

Finding missing array in array of arrays

I need to find a missing array in an "array of arrays". I started by finding this function below (on StackOverflow):
function findDeselectedItem(CurrentArray, PreviousArray) {
var CurrentArrSize = CurrentArray.length;
var PreviousArrSize = PreviousArray.length;
var deselectedItem = [];
// loop through previous array
for(var j = 0; j < PreviousArrSize; j++) {
// look for same thing in new array
if (CurrentArray.indexOf(PreviousArray[j]) == -1)
deselectedItem.push(PreviousArray[j]);
}
return deselectedItem;
}
This works just fine if you did something like this:
oldarray = ["hi", "ho", "hey"];
newarray = ["hi", "hey"];
Using findDeselectedItem(newarray, oldarray) would return ["ho"].
However, my content looks like this:
oldarray = [["James", 17, 1], ["Olivia", 16, 0], ["Liam", 18, 1]];
newarray = [["Olivia", 16, 0], ["James", 17, 1]];
How can I adapt the function above so that it returns the missing array containing 'Liam'.
Thanks
I would make a hash with the name as a key. That would make finding missing content trivial and very fast. You can then optimize the method by not rebuilding the hash every time, but only when it's really necessary.
var oldArray = [["James", 17, 1], ["Olivia", 16, 0], ["Liam", 18, 1]];
var newArray = [["Olivia", 16, 0], ["James", 17, 1]];
function findDeselectedItems(oldArray, newArray)
{
var results = [];
var hash = {};
for (var i=0; i<newArray.length; i++) {
hash[newArray[i].join(',')] = true;
}
for (var i=0; i<oldArray.length; i++) {
if (!hash[oldArray[i].join(',')]) {
results.push(oldArray[i]);
}
}
return results;
}
The problem may be that indexOf uses strict equality. I.e. if an item in the 'previous' array isn't literally also in the 'current' array, it will report it to not be in there.
You will have to iterate over the values yourself (instead of using indexOf) and check if the array contains something that is 'the same as' (but not literally the same) the array.
I.e. if I didn't explain myself well enough take a look at this;
['bob'] == ['bob']; //false
//therefore
[['bob']].indexOf(['bob']); //-1
I hope that this helps you,
function findDeselectedItem(CurrentArray, PreviousArray) {
var CurrentArrSize = CurrentArray.length;
var PreviousArrSize = PreviousArray.length;
var deselectedItem = [];
// loop through previous array
for(var j = 0; j < PreviousArrSize; j++) {
var checkArray = PreviousArrSize[j];
// loop through 2nd array to match both array
for(var i = 0; i < CurrentArrSize; i++) {
// look for same thing in new array
if (CurrentArray[i].indexOf(checkArray) == -1)
deselectedItem.push(CurrentArray[i]);
}
}
return deselectedItem;
}
#KarelG: nice and quick solution but should it not be var checkArray = PreviousArr[j]; instead of var checkArray = PreviousArrSize[j]; ?
function findDeselectedItem(CurrentArray, PreviousArray) {
var CurrentArrSize = CurrentArray.length;
var PreviousArrSize = PreviousArray.length;
var deselectedItem = [];
var selectedIndices = [];
// loop through previous array
for(var j = 0; j < PreviousArrSize; j++) {
for(k=0; k < CurrentArrSize ; k++){
if (CurrentArray[k].toString() === PreviousArray[j].toString()){
selectedIndices.push(j);
break;
}
}
}
for(var l = 0; l < PreviousArrSize; l++){
if(selectedIndices.indexOf(l) === -1){
deselectedItem.push(PreviousArray[l]);
}
}
return deselectedItem;
}
I don't think you can use indexOf to compare two arrays. You need a deeper comparison. Although this code could be written another way, you could do this with an array comparison function and using Array.some() to filter through your elements. Here's an example and a fiddle;
// Credit http://stackoverflow.com/questions/7837456/comparing-two-arrays-in-javascript
// attach the .compare method to Array's prototype to call it on any array
Array.prototype.compare = function (array) {
// if the other array is a falsy value, return
if (!array)
return false;
// compare lengths - can save a lot of time
if (this.length != array.length)
return false;
for (var i = 0; i < this.length; i++) {
// Check if we have nested arrays
if (this[i] instanceof Array && array[i] instanceof Array) {
// recurse into the nested arrays
if (!this[i].compare(array[i]))
return false;
}
else if (this[i] != array[i]) {
// Warning - two different object instances will never be equal: {x:20} != {x:20}
return false;
}
}
return true;
}
function findDeselectedItem(CurrentArray, PreviousArray) {
var CurrentArrSize = CurrentArray.length;
var PreviousArrSize = PreviousArray.length;
var deselectedItem = [];
// loop through previous array
for (var j = 0; j < PreviousArrSize; j++) {
// look for same thing in new array
CurrentArray.some(function (a, idx) {
if(PreviousArray[j].compare(a) == false) {
deselectedItem.push(PreviousArray[j]);
return true;
}
});
}
return deselectedItem;
}
var oldarray =[["James", 17, 1], ["Olivia", 16, 0], ["Liam", 18, 1]];
var newarray =[["Olivia", 16, 0], ["James", 17, 1]];
console.log(findDeselectedItem(newarray, oldarray));

how to compare two arrays of different length if you dont know the length of each one in javascript?

I am stuck in this. I got 2 arrays, I don't know the length of each one, they can be the same length or no, I don't know, but I need to create a new array with the numbers no common in just a (2, 10).
For this case:
var a = [2,4,10];
var b = [1,4];
var newArray = [];
if(a.length >= b.length ){
for(var i =0; i < a.length; i++){
for(var j =0; j < b.length; j++){
if(a[i] !=b [j]){
newArray.push(b);
}
}
}
}else{}
I don't know why my code never reach the first condition and I don't know what to do when b has more length than a.
It seems that you have a logic error in your code, if I am understanding your requirements correctly.
This code will put all elements that are in a that are not in b, into newArray.
var a = [2, 4, 10];
var b = [1, 4];
var newArray = [];
for (var i = 0; i < a.length; i++) {
// we want to know if a[i] is found in b
var match = false; // we haven't found it yet
for (var j = 0; j < b.length; j++) {
if (a[i] == b[j]) {
// we have found a[i] in b, so we can stop searching
match = true;
break;
}
// if we never find a[i] in b, the for loop will simply end,
// and match will remain false
}
// add a[i] to newArray only if we didn't find a match.
if (!match) {
newArray.push(a[i]);
}
}
To clarify, if
a = [2, 4, 10];
b = [4, 3, 11, 12];
then newArray will be [2,10]
Try this
var a = [2,4,10];
var b = [1,4];
var nonCommonArray = [];
for(var i=0;i<a.length;i++){
if(!eleContainsInArray(b,a[i])){
nonCommonArray.push(a[i]);
}
}
function eleContainsInArray(arr,element){
if(arr != null && arr.length >0){
for(var i=0;i<arr.length;i++){
if(arr[i] == element)
return true;
}
}
return false;
}
I found this solution just using the filter() and include() methods, a very and short easy one.
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
The includes() method determines whether an array includes a certain value among its entries, returning true or false as appropriate.
function compareArrays(a, b) {
return a.filter(e => b.includes(e));
}

How to efficiently build a random list from a given list without recurrences in JS?

I have a comma separated string, out of which I need to create a new string which contains a random order of the items in the original string, while making sure there are no recurrences.
For example:
Running 1,2,3,1,3 will give 2,3,1 and another time 3,1,2, and so on.
I have a code which picks a random item in the original string, and then iterates over the new string to see if it does not exist already. If it does not exist - the item is inserted.
However, I have a feeling this can be improved (in C# I would have used a hashtable, instead of iterating every time on the new array). One improvement can be removing the item we inserted from the original array, in order to prevent cases where the random number will give us the same result, for example.
I'd be happy if you could suggest improvements to the code below.
originalArray = originalList.split(',');
for (var j = 0; j < originalArray.length; j++) {
var iPlaceInOriginalArray = Math.round(Math.random() * (originalArray.length - 1));
var bAlreadyExists = false;
for (var i = 0; i < newArray.length; i++) {
if (newArray[i].toString() == originalArray[iPlaceInOriginalArray].toString()) {
bAlreadyExists = true;
break;
}
}
if (!bAlreadyExists)
newArray.push(originalArray[iPlaceInOriginalArray]);
}
Thanks!
You can still use a 'hash' in javascript to remove duplicates. Only in JS they're called objects:
function removeDuplicates(arr) {
var hash = {};
for (var i=0,l=arr.length;i<l;i++) {
hash[arr[i]] = 1;
}
// now extract hash keys... ahem...
// I mean object members:
arr = [];
for (var n in hash) {
arr.push(n);
}
return arr;
}
Oh, and the select random from an array thing. If it's ok to destroy the original array (which in your case it is) then use splice:
function randInt (n) {return Math.floor(Math.random()*n)}
function shuffle (arr) {
var out = [];
while (arr.length) {
out.push(
arr.splice(
randInt(arr.length),1 ));
}
return out;
}
// So:
newArray = shuffle(
removeDuplicates(
string.split(',') ));
// If you sort the first array, it is quicker to skip duplicates, and you can splice each unique item into its random position as you build the new array.
var s= 'Function,String,Object,String,Array,Date,Error,String,String,'+
'Math,Number,RegExp,Group,Collection,Timelog,Color,String';
var A1= s.split(',').sort(), A2= [], tem;
while(A1.length){
tem= A1.shift();
while(A1[0]== tem) tem= A1.shift();
if(tem) A2.splice(Math.floor(Math.random()*A2.length), 0, tem);
}
alert(A2.join(', '))
With your solution, you are not guaranteed not to pick same number several times, thus leaving some others of them never being picked. If the number of elements is not big (up to 100), deleting items from the source array will give the best result.
Edit
originalArray = originalList.split(',');
for (var j = 0; j < originalArray.length; j++) {
var iPlaceInOriginalArray = Math.round(Math.random() * (originalArray.length - 1 - j));
var bAlreadyExists = false;
for (var i = 0; i < newArray.length; i++) {
if (newArray[i].toString() == originalArray[iPlaceInOriginalArray].toString()) {
bAlreadyExists = true;
break;
}
}
var tmp = originalArray[originalArray.length - 1 - j];
originalArray[originalArray.Length - 1 - j] = originalArray[iPlaceInOriginalArray];
originalArray[iPlaceInOriginalArray] = tmp;
if (!bAlreadyExists)
newArray.push(originalArray[iPlaceInOriginalArray]);
}

Categories

Resources