I have an array which consist n element.
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
and also have two button next and prev and initially i am showing the first 5 element(on page load) of an array initial array [1, 2, 3, 4, 5]
how i can show the next five elements on the next button click [6, 7, 8, 9, 10] and on previous button click want to show the [1, 2, 3, 4, 5]
and also need to check the if it does not have any next element if lastIndex is included and if array includes first element.
i have tried using slice to arr.slice(begin[, end])
const arr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
const size = 5
let current = 1
function prev(){
if(current > 1){
current--
let newArr = getNewArr()
console.log(newArr)
}
}
function next(){
if(current >= 1 && current < arr.length/size){
current++
let newArr = getNewArr()
console.log(newArr)
}
}
function getNewArr(){
return arr.slice(size*current - size, size*current)
}
<button onclick=prev()>prev</button>
<button onclick=next()>next</button>
You could take an index and a size for the wanted elements ans dlice the array.
const
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
show = array => document.getElementById('items').innerHTML = array.join(' '),
next = () => {
index += size;
while (index >= data.length) index -= size;
show(data.slice(index, index + size));
},
prev = () => {
index -= size;
while (index < 0) index += size;
show(data.slice(index, index + size));
},
size = 5;
let index = 0;
document.getElementById('bprev').addEventListener('click', prev);
document.getElementById('bnext').addEventListener('click', next);
show(data.slice(index, index + size));
<button id="bprev">prev</button> <span id="items"></span> <button id="bnext">next</button>
For now I am just creating a demo with the hardcoded pageNumber in next and previous click events but you can make it dynamic based on the array size.
Working Demo :
// Input array
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// Method which returns the updated array elements based on the pageSize and pageNumber.
const paginate = (array, pageSize, pageNumber) => {
return array.slice((pageNumber - 1) * pageSize, pageNumber * pageSize);
}
// On load initializing 5 elements.
document.getElementById('content').innerHTML = paginate(arr, 5, 1);
// Next button click event
document.getElementById('next').onclick = function() {
document.getElementById('content').innerHTML = paginate(arr, 5, 2);
};
// previous button click event
document.getElementById('previous').onclick = function() {
document.getElementById('content').innerHTML = paginate(arr, 5, 1);
};
<button id="previous">Previous</button>
<span id="content"></span>
<button id="next">Next</button>
Related
I have an array that I need to divide into pages with each page showing 4 numbers. I need help on the Next and Previous page commands.
There's an answer about this before in here: How to separate my array into some parts in discord.js?, but I couldn't make it work. Using splice modifies the original array and rearranges the index so the formula there of currentPage * pageSize - pageSize for the next page start index isn't working properly.
Here are the variables for my pagination
let numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
let currentPage = 1;
let pageSize = 4;
const countPages = Math.ceil(input.length / pageSize);
Here's the code to show the initial page which shows 1, 2, 3, 4
numberArray.splice(0, pageSize);
Here's the code for Next but this outputs 9, 10, 11, 12.
const nextPage = currentPage + 1;
if (nextPage <= countPages) {
currentPage = nextPage;
const startIndex = currentPage * pageSize - pageSize;
numberArray.splice(startIndex, pageSize)
}
You shouldn't use splice as it modifies the original array. Although you already know this, you can run the following snippet and see how splice removed those four items from the original array:
let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let pageContent = array.splice(4, 4)
console.log('pageContent:', pageContent.toString())
console.log('array:', array.toString())
You could use slice instead that returns a new array:
let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let pageContent = array.slice(4, 8)
console.log('pageContent:', pageContent.toString())
console.log('array:', array.toString())
You could also create a class for this:
class Paginator {
constructor(array, pageSize) {
this.array = array;
this.pageSize = pageSize;
this.currentPage = 1;
}
getPage() {
const startIndex = (this.currentPage - 1) * this.pageSize;
return this.array.slice(startIndex, startIndex + this.pageSize);
}
next() {
if (this.currentPage * this.pageSize < this.array.length) {
this.currentPage += 1;
}
return this.getPage();
}
previous() {
if (this.currentPage > 1) {
this.currentPage -= 1;
}
return this.getPage();
}
first() {
this.currentPage = 1;
return this.getPage();
}
last() {
this.currentPage = Math.ceil(this.array.length / this.pageSize);
return this.getPage();
}
}
let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let pageSize = 4
let paginator = new Paginator(array, pageSize)
console.log(`
First: ${paginator.first()}
Next: ${paginator.next()}
Next: ${paginator.next()}
Previous: ${paginator.previous()}
Last: ${paginator.last()}
`)
Say I have 2 lists with identical items that I've shuffled like below:
listA = [1, 3, 2];
listB = [2, 3, 1];
I want to make sure that list items of the same index don't match. So I wouldn't want listA[1] to match with listB[1]. How do I randomize both lists so that this doesn't occur?
There is probably a more elegant way to do this, but the code below should work, even for arrays of different sizes. It first checks whether it's possible to get the uniqueness you're looking for, and if so it goes into a while loop to continuously shuffle the larger of the two arrays (in place) until it finds a solution.
// First, set up utility functions
function shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
function smallerAndOther(arr1, arr2) {
const smallerArr = arr1.length < arr2.length ? arr1 : arr2;
const otherArr = smallerArr === arr1 ? arr2 : arr1;
return [smallerArr, otherArr];
}
function anyEqualIdx(arr1, arr2) {
const [smallerArr, otherArr] = smallerAndOther(arr1, arr2);
for (let i of smallerArr.keys()) {
if (smallerArr[i] === otherArr[i]) return true;
}
return false;
}
function getCount(array, value) {
return array.filter((v) => (v === value)).length;
}
// Now for the real stuff
function sufficientUnique(arr1, arr2) {
const [smallerArr, otherArr] = smallerAndOther(arr1, arr2);
for (let num of new Set([...smallerArr])) {
if (otherArr.length - getCount(otherArr, num) < getCount(smallerArr, num)) {
return false;
}
}
return true;
}
function shuffleUniqueIdxs(arr1, arr2) {
if (!sufficientUnique(arr1, arr2)) {
console.log("Error: Not enough unique values to meet constraint.");
return;
}
const largerArr = arr1.length > arr2.length ? arr1 : arr2;
while (anyEqualIdx(arr1, arr2)) {
shuffleArray(largerArr);
}
console.log("Success: ", arr1, arr2);
}
// Testing
let listA = [1, 3, 2];
let listB = [2, 3, 1];
shuffleUniqueIdxs(listA, listB);
listA = [7, 5, 5, 3, 9, 9, 1];
listB = [3, 5, 5];
shuffleUniqueIdxs(listA, listB);
listA = [1, 1, 1];
listB = [2, 1, 1];
shuffleUniqueIdxs(listA, listB); // shows error message
listA = [1, 1, 1, 1, 1];
listB = [2, 2, 2, 2, 2];
shuffleUniqueIdxs(listA, listB);
listB = [99, 9, 9, 9, 9, 9, 9, 9, 99, 88, 8, 8, 8, 8, 8, 7, 7, 6, 65, 5, 5, 5, 4]
listA = [9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 6];
shuffleUniqueIdxs(listA, listB);
Here's one solution. It first individually shuffles both arrays, then it looks for repeated entries and randomly moves those around. Note that this solution only works for arrays of the same size. It is also intended to be used on arrays where most elements are unique (otherwise, it might get stuck randomly moving things around for a while).
const randIntBetween = (left, right) => left + Math.floor(Math.random() * (right - left));
function shuffle(array) {
array = [...array];
for (let i = 0; i < array.length; ++i) {
const newIndex = randIntBetween(i, array.length);
[array[i], array[newIndex]] = [array[newIndex], array[i]];
}
return array;
}
function randomlyMoveRepeatedEntries(array, comparisonArray) {
array = [...array];
const indicesToCheck = new Set(array.map((_, i) => i));
while (indicesToCheck.size) {
const { value: index } = indicesToCheck.values().next();
if (array[index] !== comparisonArray[index]) {
indicesToCheck.delete(index);
continue;
}
const newIndex = randIntBetween(index, array.length);
[array[index], array[newIndex]] = [array[newIndex], array[index]];
indicesToCheck.add(newIndex);
}
return array;
}
// ----- Example Usage ----- //
const listA = shuffle([1, 2, 3, 4, 5]);
const listB = randomlyMoveRepeatedEntries(shuffle([1, 2, 3, 4, 5]), listA);
console.log(listA.join(', '));
console.log(listB.join(', '));
I have an array [1,1,1,1,2,3,4,5,5,6,7,8,8,8]
How can I get an array of the distinct duplicates [1,5,8] - each duplicate in the result only once, regardless of how many times it appears in the original array
my code:
var types = availControls.map(item => item.type);
var sorted_types = types.slice().sort();
availControlTypes = [];
for (var i = 0; i < sorted_types.length - 1, i++) {
if (sorted_types[i + 1] == sorted_types[i])
availControlTypes.push(sorted_types[i]);
}
This gets me the duplicates, but not unique.
This will do it
var input = [1, 1, 1, 1, 2, 3, 4, 5, 5, 6, 7, 8, 8, 8];
let filterDuplicates = arr => [...new Set(arr.filter((item, index) => arr.indexOf(item) != index))]
console.log(filterDuplicates(input))
You need a for loop, with an object that will hold the number of times the number appeared in the array. When the count is already 1, we can add the item to the result. We should continue to increment the counter, so we won't add more than a single duplicate of the same number (although we can stop at 2).
function fn(arr) {
var counts = {};
var result = [];
var n;
for(var i = 0; i < arr.length; i++) {
n = arr[i]; // get the current number
if(counts[n] === 1) result.push(n); // if counts is exactly 1, we should add the number to results
counts[n] = (counts[n] || 0) +1; // increment the counter
}
return result;
}
var arr = [1, 1, 1, 1, 2, 3, 4, 5, 5, 6, 7, 8, 8, 8];
var result = fn(arr);
console.log(result)
const dupes = arr =>
Array.from(
arr.reduce((acc, item) => {
acc.set(item, (acc.get(item) || 0) + 1);
return acc;
}, new Map())
)
.filter(x => x[1] > 1)
.map(x => x[0]);
const arr = [1, 1, 1, 1, 2, 3, 4, 5, 5, 6, 7, 8, 8, 8];
console.log(dupes(arr));
// [ 1, 5, 8 ]
ES6 1 liner.
This is very similar to how we find unique values, except instead of filtering for 1st occurrences, we're filtering for 2nd occurrences.
let nthOccurrences = (a, n = 1) => a.filter((v, i) => a.filter((vv, ii) => vv === v && ii <= i).length === n);
let x = [1, 1, 1, 1, 2, 3, 4, 5, 5, 6, 7, 8, 8, 8];
let uniques = nthOccurrences(x, 1);
let uniqueDuplicates = nthOccurrences(x, 2);
let uniqueTriplets = nthOccurrences(x, 3); // unique values with 3 or more occurrences
console.log(JSON.stringify(uniques));
console.log(JSON.stringify(uniqueDuplicates));
console.log(JSON.stringify(uniqueTriplets));
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const output = move(numbers, 3, -5);
console.log(output);
function move(array, index, offset) {
const output = [...array];
const element = output.splice(index, 1)[0];
output.splice(index + offset, 0, element)
return output;
}
The first line is an array of numbers.
At the second line, when calling the move function, we pass three arguments.
First, is the array itself called numbers.
Secondly, the index of the number we are trying to move (in the example, we have index 3 so we are passing the number 4).
Finally, we have the offset set to -5. The negative sign means we are moving the number to the left. The 5 means 5 positions.
But as you can see, we only have 3 positions to the left of the number 4 before reaching the beginning of the array. In this case, we have to go to the end of the array and count backwards. So, we are looking for a function which will turn the original array to [1, 2, 3, 5, 6, 7, 8, 4, 9].
As you can see, number 4 has shifted 3 positions to the left to reach the beginning of the array, then, 2 further positions from the end of the array.
A further example to clarify.
Let's say we write:
const output = move(numbers, 1, -4);
In this example, we want the number 2 from the array (index 1) to move 4 positions to the left. So, we should get [1, 3, 4, 5, 6, 7, 2, 8, 9].
You need to cover the edge cases when the updated index is less than 0 OR greater than the array length. You can try following
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
function move(array, index, offset) {
const output = [...array];
const element = output.splice(index, 1)[0];
let updatedIndex = index + offset;
if(updatedIndex < 0) updatedIndex++;
else if (updatedIndex >= array.length) updatedIndex -= array.length;
output.splice(updatedIndex, 0, element);
return output;
}
console.log(move(numbers, 3, -5));
You could do this using while loop and iterating for the Math.abs() of the position you want to move to and then move in direction depending if parameter is positive or negative.
function move(arr, i, p) {
let left = p < 0,
counter = Math.abs(p),
newPos = i;
while (--counter > -1) {
newPos = (left ? (newPos - 1) : (newPos + 1));
if (newPos == -1) newPos = arr.length - 1;
if (newPos == arr.length) newPos = 0;
if (counter == 0) arr.splice(newPos, 0, arr.splice(i, 1)[0])
}
return arr;
}
console.log(move([1, 2, 3, 4, 5, 6, 7, 8, 9], 3, -5));
console.log(move([1, 2, 3, 4, 5, 6, 7, 8, 9], 5, 5));
console.log(move([1, 2, 3, 4, 5, 6, 7, 8, 9], 1, -25));
I am taking an excercise on codewars:
Given a list of integers and a single sum value, return the first two
values (parse from the left please) in order of appearance that add up
to form the sum.
Example:
sum_pairs([10, 5, 2, 3, 7, 5], 10)
# ^-----------^ 5 + 5 = 10, indices: 1, 5
# ^--^ 3 + 7 = 10, indices: 3, 4 *
# * entire pair is earlier, and therefore is the correct answer
== [3, 7]
What do you think entire pair is earlier means? IMO if the sum of it's indexes is smallest. Now based on this assumption I made my solution and one test fails:
var sum_pairs=function(ints, s){
let i = 0;
let pair = [0, 0];
let ind = [100, 100]
let found = false;
function loop(i) {
if (i > ints.length) return pair;
ints.slice(i).forEach((curr, idx) => {
ints.slice(i+1).some((num, i) => {
let sum = curr + num;
let prevIndicies = ind[0] + ind[1];
if(sum === s && prevIndicies > idx + i) {
ind = [idx, i];
pair = [curr, num];
found = true;
return true;
}
})
})
i += 1;
loop(i)
}
loop(0)
if (found) {
return pair
}
return undefined;
}
console.log(sum_pairs([1,4,8,7,3,15], 8))
Test returns error that [1, 7] is expected.
I'm pretty sure what it means is they want the second element to be as leftward in the list as possible. For example, for
l5= [10, 5, 2, 3, 7, 5];
when trying to find a sum of 10, the desired output is
[3, 7]
[10, 5, 2, 3, 7, 5];
^ ^
instead of
[5, 5]
[10, 5, 2, 3, 7, 5];
^ ^
because the last element in [3, 7], the 7, came before the second 5.
This code seems to pass all test cases - iterate in a triangular fashion, starting at indicies [0, 1], [0, 2], [1, 2], [0, 3], [1, 3], [2, 3], ...:
const sum_pairs = function(ints, s){
const { length } = ints;
for (let i = 1; i < length; i++) {
for (let j = 0; j < i; j++) {
if (ints[i] + ints[j] === s) return [ints[j], ints[i]];
}
}
}
const sum_pairs=function(ints, s){
const { length } = ints;
for (let i = 1; i < length; i++) {
for (let j = 0; j < i; j++) {
if (ints[i] + ints[j] === s) return [ints[j], ints[i]];
}
}
}
l1= [1, 4, 8, 7, 3, 15];
l2= [1, -2, 3, 0, -6, 1];
l3= [20, -13, 40];
l4= [1, 2, 3, 4, 1, 0];
l5= [10, 5, 2, 3, 7, 5];
l6= [4, -2, 3, 3, 4];
l7= [0, 2, 0];
l8= [5, 9, 13, -3];
console.log(sum_pairs(l1, 8))
console.log(sum_pairs(l2, -6))
console.log(sum_pairs(l3, -7))
console.log(sum_pairs(l4, 2))
console.log(sum_pairs(l5, 10))
console.log(sum_pairs(l6, 8))
console.log(sum_pairs(l7, 0))
console.log(sum_pairs(l8, 10))
It means that you go from left to right and take the first matching pair, and since 7 is the first element that creats a pair (going from the left) 3 and 7 is the first pair.
I would solve it a bit easier:
function sum_pairs(arr, target) {
let old = [];
let result = [];
arr.some((el) => {
let found = old.find((oldEl) => oldEl + el === target);
if (found) return result = [found, el];
old.push(el);
})
return result;
}
sum_pairs([10, 5, 2, 3, 7, 5], 10);
Edit: an explaination. I loop over all elements in the array searching for a match i all the elements I have passed. If I find a match I remember it and break out of the loop by returning a "truthy" value. (That is just how .some() works.) Finally if I have not found a match I add the element to my list of old elements and go on to the next.
function sum_pair(arr,sum){
let result = [];
arr.forEach((i, j)=>{
if(i+arr[j+1]===sum){
console.log(i,arr[j+1], i+arr[j+1])
}
})
}
sum_pair([0, 3, 7, 0, 5, 5],10)