List sequential subset elements in Javascript - javascript

I have an Array a = [0,1,2,3,4,5,6]
and I want to subset with 3 elements so the result becomes this:
[0,1,2],[1,2,3],[2,3,4],[3,4,5],[4,5,6]
I tried using this script that I found :
Array.prototype.combinate = function( iItems, aIn ) {
if (!aIn) {
var aIn = new Array();
this.combinate.aResult = new Array();
}
for(var i = 0; i < this.length; i++) {
var a = aIn.concat(this[i]);
var aRest = this.concat(); // Concat with nothing to create copy
aRest.splice(0, i + 1);
if(iItems && iItems - 1 <= aRest.length) {
aRest.combinate(iItems - 1, a);
if(iItems == 1) this.combinate.aResult.push(a);
}
}
return this.combinate.aResult;
}
But this gives all possible subset (and become easily slow when the list becomes big and the search subset is small) - I only need the "sequential" subset like shown above - so like [1,2,3] is ok - but not [1,2,4] ..
Any bright people out there who knows how to do this in JavaScript ..?

Assuming the array in question does not need to be sorted in some way first, I would do it this way:
function combinate(arr) {
var results = [];
if (arr.length >= 3) {
for (var i = 0; i < arr.length - 2; i++) {
var slice = arr.slice(i, i + 3);
results.push(slice);
}
}
return results;
}
As an additional note, I would recommend against adding something like this as a method to the Array prototype. Nothing stopping you from doing so if you need to for some reason, but I would avoid it.

Try this:
for (var i = 0; i < arr.length - 2; i++) {
var combination = new Array(arr[i], arr[i + 1], arr[i + 2]);
// or this
// var combination = [arr[i], arr[i + 1], arr[i + 2]];
// do something with the new array ??
}

Related

Weird array behavior in JavaScript

I'm trying to write a tool for visualizing the bubble sort algorithm.
The array arr holding all the values, that is to be sorted, is a global variable. The user clicks the "Fill" button btnFill to fill the array with unsorted, random numbers using the fillArray function. The function returns an array of objects: {val: x, col: "y"} where x is the value and col is a color class used for CSS.
When the array is filled, if the user clicks the "sort" button btnSort, the bubbleSort function is invoked where I guess my problem is:
This function saves a copy of the array arr on every iteration of the inner loop. This is an idea that I had since I was having a lot of issues using setInterval to animate - I could just save snapshots of the array during every stage of the sorting, and then pass it to the draw function so that there wouldn't be any JavaScript weirdness combining loops and intervals.
The function finishes running and is expected (by me at least) to return an array filled with copies of the arr array from every loop iteration.
The actual behavior which I have tried to understand for hours is that the snapShot array is filled with arrays of a sorted arr. All elements are the same - sorted arrays. Doesn't make sense to me since when debugging it comes out as sorted in console.log when it enters the sorting loop for the first time.
I appreciate any help greatly, thank you!
--EDIT--
I'm aware that the snapShot array gets sent as an array of arrays and will not be drawn to the screen but the problem is somewhere before that. That part was changed for debugging reasons
const btnFill = document.querySelector("#btnFill");
const btnSort = document.querySelector("#btnSort");
const container = document.querySelector(".container");
let arr = [];
btnFill.addEventListener("click", function () {
arr = fillArray();
draw(arr);
});
btnSort.addEventListener("click", function () {
let sorted = bubbleSort();
draw(sorted);
});
function bubbleSort() {
let snapShots = [];
for (let i = 0; i < arr.length - 1; i++) {
for (let j = 0; j < arr.length - 1 - i; j++) {
if (arr[j].val > arr[j + 1].val) {
let tmp = arr[j].val;
arr[j].val = arr[j + 1].val;
arr[j + 1].val = tmp;
snapShots.push([...arr]);
}
}
}
return snapShots;
}
function fillArray() {
const tmp = [];
const len = 50;
for (let i = 0; i < len; i++) {
tmp[i] = { val: Math.floor(Math.random() * 100 + 1), col: "red" };
}
return tmp;
}
function draw(array) {
container.innerHTML = "";
for (let i = 0; i < array.length; i++) {
const tmp = document.createElement("div");
tmp.style.height = array[i].val + "%";
tmp.classList.add("bar", array[i].col);
container.appendChild(tmp);
}
}
The reason that it's not working like you want it is because you are doing shallow copies of the array, but the objects in each position are the same references.
This means that this part of the code:
let tmp = arr[j].val;
arr[j].val = arr[j + 1].val;
arr[j + 1].val = tmp;
Is changing the object that every snapshot element is pointing in the same position. And that's why you get every array sorted, because you are creating new arrays with the same references to the objects.
To get what you want you can do a deep copy instead, which also creates new references of the nested values.
function bubbleSort() {
let snapShots = [];
for (let i = 0; i < arr.length - 1; i++) {
for (let j = 0; j < arr.length - 1 - i; j++) {
if (arr[j].val > arr[j + 1].val) {
let tmp = arr[j].val;
arr[j].val = arr[j + 1].val;
arr[j + 1].val = tmp;
snapShots.push(JSON.parse(JSON.stringify(arr)));
}
}
}
return snapShots;
}
Other solution (and simpler) is to change the position of the object in the array instead of changing the property val of the object:
function bubbleSort() {
let snapShots = [];
for (let i = 0; i < arr.length - 1; i++) {
for (let j = 0; j < arr.length - 1 - i; j++) {
if (arr[j].val > arr[j + 1].val) {
let tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
snapShots.push([...arr]);
}
}
}
return snapShots;
}

How to get the product of numbers gotten from combinations of datasets

I have a combinatoric script that's working fine, actually got most of it from the IBM dev website. But I want to be able to not just show the possible combinations, but also extract the numbers on each combination and get the product of the entire numbers. The project am working on mixes numbers (quantity) with strings (codename). So after combining them, i extract the number from each string and get the product of all the numbers in each combination. As shown;
[A2,B4,C5] = 2*4*5 = 40
Here is my javascript code that gets the combination, not to worry, I ran it with a test array of numbers 1-6, without the characters as shown above.
var Util = function() {
};
Util.getCombinations = function(array, size, start, initialStuff, output) {
if (initialStuff.length >= size) {
output.push(initialStuff);
} else {
var i;
for (i = start; i < array.length; ++i) {
Util.getCombinations(array, size, i + 1, initialStuff.concat(array[i]), output);
}
}
}
Util.getAllPossibleCombinations = function(array, size, output) {
Util.getCombinations(array, size, 0, [], output);
}
// Create an array that holds numbers from 1 ... 6.
var array = [];
for (var i = 1; i <= 6; ++i) {
array[i - 1] = i;
}
var output = [];
var resultArray = [];
Util.getAllPossibleCombinations(array, 4, output);
for(var j=0; j<output.length; j++) {
resultArray += output[j] + "=" + "<br />";
}
document.getElementById("test").innerHTML = resultArray;
});
I tried running this code inside the last for loop to get my multiplication, but it's just not executing, i must be doing something wrong. Here is the code;
var inputval = output[j].replace(/[^,.0-9]/g, '');
inputval = inputval.slice(0, -1);
var hoArray = inputval.split(',');
var cunt= hoArray.length;
var ans=1;
for(var m=0; m<cunt; m++)
{
ans *= hoArray[m];
}
Thanks for your assistance in advance.
walk the array then walk the string, then cast and see if it is an integer then tally and sum the product.
let array = ['A20', 'B11', 'C5'];
function getProduct(ar) {
let product = 1;
for (let x of ar) {
let semiProduct = [];
for (let i of x) {
if (Number.isInteger(+i)) {
semiProduct.push(i);
}
}
product *= semiProduct.join('');
}
return product;
}
console.log(getProduct(array))
You could also use a regular expression.
let array = ['A20', 'B11', 'C5'];
function getProduct(ar) {
let product = 1;
for (let x of ar) {
product *= x.match(/\d+/)[0];
}
return product;
}
console.log(getProduct(array))
If you want a way to generate permutations, you can utilize a generator to make things more concise.
let array = ['A20', 'B11', 'C5'];
function* permu(arr, l = arr.length) {
if (l <= 0) yield arr.slice();
else
for (var i = 0; i < l; i++) {
yield* permu(arr, l - 1);
const j = l % 2 ? 0 : i;
[arr[l - 1], arr[j]] = [arr[j], arr[l - 1]];
}
}
console.log(
Array.from(permu(array))
);
When I run that code in the console it throws an error because output[j] is an array [1,2,3,4] and it looks like you're expecting it to be a string. Arrays do not have a replace method in JS.
You should run this:
var count= hoArray.length;
var ans=1;
for(var m=0; m<count; m++)
{
ans *= hoArray[m];
}
And put output[j] instead of hoArray. And don't do any of this:
var inputval = output[j].replace(/[^,.0-9]/g, '');
inputval = inputval.slice(0, -1);
var hoArray = inputval.split(',');

Get elements that has no double value in an array

I have a question . How do you retrieve elements that has no double value in an array?? For example: [1,1,2,2,3,4,4,5] then you retrieve [3,5] only.
Thanks in advance
for (var j = 0; j < newArr.length; j++) {
if ((arr1.indexOf(newArr[j]) === 0) && (arr2.indexOf(newArr[j]) === 0)) {
index = newArr.indexOf(j); newArr.splice(index, 1);
}
}
If the item in the array is unique then the index found from the beginning should equal the index found from the end, in other words:
var xs = [1, 1, 2, 2, 3, 4, 4, 5];
var result = xs.filter(function(x) {
return xs.indexOf(x) === xs.lastIndexOf(x);
});
console.log(result); //=> [3, 5]
sorry for the presentation its my first post !
You have to compare each element of your array to the others in order to get the number of occurence of each element
var tab = [1,1,2,2,3,4,4,5] //The array to analyze
tab = tab.sort(); // we sort the array
show(tab); // we display the array to the console (F12 to open it)
var uniqueElementTab = []; // this array will contain all single occurence
var sameElementCounter = 0;
for(x=0;x<tab.length;x++){ // for all element in the array
sameElementCounter = 0;
for(y=0;y<tab.length;y++){ // we compare it to the others
if((tab[x]==tab[y])){
sameElementCounter+=1; // +1 each time we meet the element elsewhere
}
}
if(sameElementCounter<=1){
uniqueElementTab.push(tab[x]); //if the element is unique we add it to a new array
}
}
show(uniqueElementTab); // display result
function show(tab) { // Simple function to display the content of an array
var st="";
for(i=0;i<tab.length;i++){
st += tab[i]+" ";
}
console.log(st+"\n");
}
Hope it helps.
Here is a simple "tricky" solution using Array.sort, Array.join, Array.map, String.replace and String.split functions:
var arr = [1, 1, 2, 2, 3, 4, 4, 5];
arr.sort();
var unique = arr.join("").replace(/(\d)\1+/g, "").split("").map(Number);
console.log(unique); // [3, 5]
create new array tmp,and check already value exist by indexOf .If existed delete by splice function..
var arr = [1,1,2,2,3,4,4,5];
var tmp = [];
var dup = [];
for(var i = 0; i < arr.length; i++){
var ind = tmp.indexOf(arr[i]);
if(ind == -1){
if(dup.indexOf(arr[i]) == -1){
tmp.push(arr[i]);
}
}
else{
tmp.splice(ind,1);
dup.push(arr[i]);
}
}
console.log(tmp);
This would be my way of doing this job.
var arr = [1,1,2,2,3,4,4,5],
uniques = Object.keys(arr.reduce((p,c) => (c in p ? Object.defineProperty(p, c, {enumerable : false,
writable : true,
configurable : true})
: p[c] = c,
p), {}));
console.log(uniques);
A solution for unsorted arrays with a hash table for the items. Complexity O(2n)
var array = [1, 1, 2, 2, 3, 4, 4, 5, 1],
hash = Object.create(null),
single;
array.forEach(function (a, i) {
hash[a] = a in hash ? -1 : i;
});
single = array.filter(function (a, i) {
return hash[a] === i;
});
console.log(single);
If the array is sorted, you can solve this in O(n) (see "pushUniqueSinglePass" below):
function pushUniqueSinglePass(array, unique) {
var prev; // last element seen
var run = 0; // number of times it has been seen
for (var i = 0; i < array.length; i++) {
if (array[i] != prev) {
if (run == 1) {
unique.push(prev); // "prev" appears only once
}
prev = array[i];
run = 1;
} else {
run++;
}
}
}
function pushUniqueWithSet(array, unique) {
var set = new Set();
for (var i = 0; i < array.length; i++) {
set.add(array[i]);
}
for (let e of set) {
unique.push(set);
}
}
// Utility and test functions
function randomSortedArray(n, max) {
var array = [];
for (var i = 0; i < n; i++) {
array.push(Math.floor(max * Math.random()));
}
return array.sort();
}
function runtest(i) {
var array = randomSortedArray(i, i / 2);
var r1 = [],
r2 = [];
console.log("Size: " + i);
console.log("Single-pass: " + time(
pushUniqueSinglePass, array, r1));
console.log("With set: " + time(
pushUniqueWithSet, array, r2));
// missing - assert r1 == r2
}
[10, 100, 1000, 10000,
100000, 1000000
].forEach(runtest);
function time(fun, array, unique) {
var start = new Date().getTime();
fun(array, unique);
return new Date().getTime() - start;
}
This is much more efficient than using maps or sorting (time it!). In my machine, a 1M sorted array can have its unique elements found in 18 ms; while the version that uses a set requires 10x more.

Reversing certain number of elements in an array javascript

I am working on a code where I need to reverse certain no of elements in an array and rest should remain same. For example is an array has values of 1,2,3,4,5,6 and I have to reverse 4 elements of it then output should be 4,3,2,1,5,6. I am using below code to achieve this but getting error, please suggest.
function reverseArray(n, a) {
var interimArray1 = [];
//var interimArray2=[];
//var finalArray=[];
for (var i < n; i >= 0; i--) {
interimArray1.push[a[i]];
}
for (var i = n; i < a.length; i++) {
interimArray1.push[a[i]];
}
for (var i = 0; i < interimArray1.length; i++) {
console.log(interimArray1[i]);
}
}
var arr = [1, 2, 3, 4, 5, 6];
var num = 4;
reverseArray(num, arr);
The error in your code is that you intend to call the push method on a[i] like so:
interimArray1.push(a[i]);
but instead you write:
interimArray1.push[a[i]];
You make that mistake twice. To give arguments to the push method, you must use round parenthesis ().
With that fixed, you will see that your code works perfectly.
You can use Array#slice, Array#splice as follow.
function partialReverse(arr, num, from = 0) {
var slicedArr = arr.slice(from, num + from);
arr.splice(from, num); // Remove `num` items from array
arr.splice(from, 0, ...slicedArr.reverse()); // Add `num` reversed items
return arr;
}
var arr = [1, 2, 3, 4, 5, 6];
console.log(partialReverse(arr, 4, 0)); // Reverse four items from `arr` starting from 0th index
console.log(partialReverse(arr, 4, 1)); // Reverse four items from `arr` starting from 1st index
Lots of hints but you seem to be missing them. ;-)
You need to assign an initial value to i, so:
for (var i = n; ... )
===========^
Also, you need to use () to call functions, not [], so:
interimArray1.push(a[i]);
==================^====^
Same in the following for block. Otherwise, the code works though it's more verbose than it needs to be.
This is working :
I'm sure there are faster ways of doing it. Also, it will only work for elements at the beginning of the array but you can adjust the function for what you want to achieve.
var reverseArray = function(arr,elementsToReverse) {
var tempArrayRev = [];
var tempArray = [];
for (var i=0;i<arr.length;i++) {
if (i < elementsToReverse) {
tempArrayRev[i] = arr[i];
} else {
tempArray.push(arr[i]);
}
}
return tempArrayRev.reverse().concat(tempArray);
}
var array = [1,2,3,4,5,6];
document.getElementById('arrayOutput').innerHTML += reverseArray(array,4);
<div id="arrayOutput">Array :<br></div>
This is the answer you can test it.
function reverseArray(n, a) {
var interimArray1 = [];
for (var i = 0; i < a.length; i++) {
interimArray1.push(a[i]);
}
for (var i = num; i >=0; i--) {
interimArray1[i-1] = a[n - i];
}
for (var i = 0; i < interimArray1.length; i++) {
console.log(interimArray1[i]);
}
}
var arr = [1, 2, 3, 4, 5, 6];
var num = 4;
reverseArray(num, arr);
You could use something like this.
function reverseArray(n, arrIn) {
// Splice splits the array in 2 starting at 0 index going n long
var arrOut = arrIn.splice(0,n);
// reverse is pretty straight forward
arrOut = arrOut.reverse();
// Concat joins the two together
return arrOut.concat(arrIn);
}

Alternate method to splice function in JavaScript

Hi i am working on LIME programming which is a subset of javascript.
i need to use javascript.splice to remove certain elements from my array, sad to say, LIME does not support splice function.
Any idea how do i create my own function to remove elements from an array?
Thanks for your time.
EDIT: Manage to create a simple function.
function removeElements(array, index)
{
var tempArray = new Array();
var counter = 0;
for(var i = 0; i < array.length; i++)
{
if(i != index)
{
tempArray[counter] = array[i];
counter++;
}
}
return tempArray;
}
Array.prototype.splice is fully defined in ECMA-262 §15.4.4.12, so use that as your spec and write one. e.g.
15.4.4.12 Array.prototype.splice (start, deleteCount [ , item1 [ ,item2 [ , … ] ] ] )
When the splice
method is called with two or more
arguments start, deleteCount and
(optionally) item1, item2, etc., the
deleteCount elements of the array
starting at array index start are
replaced by the arguments item1,
item2, etc. An Array object containing
the deleted elements (if any) is
returned. The following steps are
taken:...
You will probably have to create a new array, copy the members up to start from the old array, insert the new members, then copy from start + deleteCount to the end to the new array.
Edit
Here is an amended splice, the first I posted was incorrect. This one splices the array passed in and returns the removed members. It looks a bit long but I tried to keep it close to the spec and not assume support for any complex Array methods or even Math.max/min. It can be simplified quite a bit if they are.
If push isn't supported, it can be replaced fairly simply too.
function arraySplice(array, start, deleteCount) {
var result = [];
var removed = [];
var argsLen = arguments.length;
var arrLen = array.length;
var i, k;
// Follow spec more or less
start = parseInt(start, 10);
deleteCount = parseInt(deleteCount, 10);
// Deal with negative start per spec
// Don't assume support for Math.min/max
if (start < 0) {
start = arrLen + start;
start = (start > 0)? start : 0;
} else {
start = (start < arrLen)? start : arrLen;
}
// Deal with deleteCount per spec
if (deleteCount < 0) deleteCount = 0;
if (deleteCount > (arrLen - start)) {
deleteCount = arrLen - start;
}
// Copy members up to start
for (i = 0; i < start; i++) {
result[i] = array[i];
}
// Add new elements supplied as args
for (i = 3; i < argsLen; i++) {
result.push(arguments[i]);
}
// Copy removed items to removed array
for (i = start; i < start + deleteCount; i++) {
removed.push(array[i]);
}
// Add those after start + deleteCount
for (i = start + (deleteCount || 0); i < arrLen; i++) {
result.push(array[i]);
}
// Update original array
array.length = 0;
i = result.length;
while (i--) {
array[i] = result[i];
}
// Return array of removed elements
return removed;
}
If you don't care about order of the array and you're just looking for a function to perform splice, here's an example.
/**
* Time Complexity: O(count) aka: O(1)
*/
function mySplice(array, start, count) {
if (typeof count == 'undefined') count = 1
while (count--) {
var index2remove = start + count
array[index2remove] = array.pop()
}
return array
}
If you want to return the removed elements like the normal splice method does this will work:
/**
* Time Complexity: O(count) aka: O(1)
*/
function mySplice(array, index, count) {
if (typeof count == 'undefined') count = 1
var removed = []
while (count--) {
var index2remove = index + count
removed.push(array[index2remove])
array[index2remove] = array.pop()
}
// for (var i = index; i < index + count; i++) {
// removed.push(array[i])
// array[i] = array.pop()
// }
return removed
}
This modifies the original Array, and returns the items that were removed, just like the original.
Array.prototype.newSplice = function( start, toRemove, insert ) {
var remove = this.slice( start, start + toRemove );
var temp = this.slice(0,start).concat( insert, this.slice( start + toRemove ) );
this.length = 0;
this.push.apply( this, temp );
return remove;
};
Comparison test: http://jsfiddle.net/wxGDd/
var arr = [0,1,2,3,4,5,6,7,8];
var arr2 = [0,1,2,3,4,5,6,7,8];
console.log( arr.splice( 3, 2, 6 ) ); // [3, 4]
console.log( arr ); // [0, 1, 2, 6, 5, 6, 7, 8]
console.log( arr2.newSplice( 3, 2, 6 ) ); // [3, 4]
console.log( arr2 ); // [0, 1, 2, 6, 5, 6, 7, 8]
It could use a little extra detail work, but for the most part it takes care of it.
Here is a simple implement in case the Array.prototype.splice dispears
if (typeof Array.prototype.splice === 'undefined') {
Array.prototype.splice = function (index, howmany, elemes) {
howmany = typeof howmany === 'undefined' || this.length;
var elems = Array.prototype.slice.call(arguments, 2), newArr = this.slice(0, index), last = this.slice(index + howmany);
newArr = newArr.concat.apply(newArr, elems);
newArr = newArr.concat.apply(newArr, last);
return newArr;
}
}
Are there any other methods that are missing in LIME's Array implementation?
Assuming at least the most basic push() and indexOf() is available, there's several ways you could do it. How this is done would depend on whether this is destructive method or whether it should return a new array. Assuming the same input as the standard splice(index, howMany, element1, elementN) method:
Create a new array named new
push() indexes 0 to index onto the new array
Now stop at index and push() any new elements passed in. If LIME supports the standard arguments variable then you can loop through arguments with index > 2. Otherwise you'll need to pass in an array instead of a variable number of parameters.
After inserting the new objects, continue looping through the input array's elements, starting at index + howMany and going until input.length
I believe that should get you the results you're looking for.
I have used this below function as an alternative for splice()
array = mySplice(array,index,count);
above is the function call,
And this is my function mySplice()
function mySplice(array, index, count)
{
var newArray = [];
if( count > 0 )
{ count--;}
else
{ count++;}
for(i = 0; i <array.length; i++)
{
if(!((i <= index + count && i >= index) || (i <= index && i >= index + count)))
{
newArray.push(array[i])
}
}
return newArray;
}
I have done it very similar way using only one for loop
function removeElements(a,index,n){
// a=> Array , index=> index value from array to delete
// n=> number of elements you want to delete
let temp = []; // for storing deleted elements
let main_array = []; // for remaining elements which are not deleted
let k = 0;
for(let i=0;i<a.length;i++){
if((i===index) || ((index<i && i<n+index))){
temp[i]=a[i+1];
delete a[i];
}
if(a[i]!==undefined){
main_array[k] = a[i];
a[i] = main_array[k];
k++;
}
}
a=main_array;
return a;
}
a=[1,2,3,4,5];
console.log(removeElements(a,0,1));
follow link Jsfiddle
var a = [3, 2, 5, 6, 7];
var fromindex = 1
var toindex = 2;
for (var i = 0; i < a.length; i++) {
if (i >= fromindex + toindex || i < fromindex) {
console.log(a[i])
}
}
var a = [3, 2, 5, 6, 7];
var temp=[];
function splice(fromindex,toindex)
{
for (var i = 0; i < a.length; i++) {
if(i>=fromindex+toindex || i<fromindex)
{
temp.push(a[i])
}
}
return temp
}
console.log(splice(3,2))

Categories