Create a New Index Array - javascript

Not sure why this isn't working.
Instructions:
// Create a function called indexFinder that will loop over an array and return a new array of the indexes of the contents e.g. [243, 123, 4, 12] would return [0,1,2,3]. Create a new variable called 'indexes' and set it to contain the indexes of randomNumbers.
Tried Solution:
let randomNumbers = [1, 3453, 34, 456, 32, 3, 2, 0];
let indexes = [];
function indexFinder(arr){
for(var i = 0; arr.length; i++){
indexes.push(i);
}
return indexes;
}
indexFinder(randomNumbers);
console.log(indexes);

You have no real condition test in your for loop because arr.length, when above 0, is always truthy.
let randomNumbers = [1, 3453, 34, 456, 32, 3, 2, 0];
let indexes = [];
function indexFinder(arr){
for(var i = 0; i < arr.length; i++){
indexes.push(i);
}
return indexes;
}
indexFinder(randomNumbers);
console.log(indexes);
But there's a much more concise way of doing this:
const randomNumbers = [1, 3453, 34, 456, 32, 3, 2, 0];
const indexFinder = arr => arr.map((_, i) => i);
console.log(indexFinder(randomNumbers));

Another method is using Array.from
const randomNumbers = [1, 3453, 34, 456, 32, 3, 2, 0];
console.log(Array.from(randomNumbers, x => randomNumbers.indexOf(x)));
Or we can use keys
const randomNumbers = [1, 3453, 34, 456, 32, 3, 2, 0];
console.log([...Array(randomNumbers.length).keys()])

The problem is the condition within that for-loop using just arr.length because for length greater than 0 will be always true.
An alternative is using the function Array.from:
let randomNumbers = [1, 3453, 34, 456, 32, 3, 2, 0],
indexes = Array.from({length: randomNumbers.length}, (_, i) => i);
console.log(indexes);
Another alternative is getting the length and then execute a simple for-loop.

Related

Sorting an array by their ascending value within the array in JS

It's a bit of a tricky situation I'm in, but I have an array like this:
const nums = [32, -3, 62, 8, 121, -231, 62, 13];
and need to replace them by their corresponding ascending index. The above example should yield:
[4, 1, 5, 2, 7, 0, 6, 3]
The solution I've come up with is this: TS Playground
const nums = [32, -3, 62, 8, 121, -231, 62, 13];
const numsCopy = nums.map(e => e);
// Basic sorting
for (let i = 0; i < numsCopy.length; i++) {
for (let j = 0; j < numsCopy.length; j++) {
if (numsCopy[i] < numsCopy[j]) {
let t = numsCopy[j];
numsCopy[j] = numsCopy[i];
numsCopy[i] = t;
}
}
}
for (let i = 0; i < numsCopy.length; i++) {
let sortedValue = numsCopy[i];
nums[nums.indexOf(sortedValue)] = i;
}
Problems arise however when I change nums to include a value nums.length > n >= 0. The call nums.indexOf(...) may return a faulty result, as it may have already sorted an index, even though it exists somewhere in the array.
If you replace nums with these values, -231 will have an index of 2 for some reason...
const nums = [32, -3, 62, 7, 121, -231, 62, 13, 0];
> [5, 1, 6, 3, 8, 2, 7, 4, 0]
Is there a better approach to this problem, or a fix to my solution?
You could sort the indices by the value and create a new array with index values a sorted positions.
to get the wanted result call the sorting function again and you get the indices sorted by the index order.
const
sort = array => [...array.keys()].sort((a, b) => array[a] - array[b]),
fn = array => sort(sort(array));
console.log(...fn([32, -3, 62, 8, 121, -231, 62, 13])); // 4 1 5 2 7 0 6 3
console.log(...fn([-1, 3, 1, 0, 2, 9, -2, 7])); // 1 5 3 2 4 7 0 6
Copy the array, sort its values, get indexOf, and null the value in the sorted copy:
const sortIndicesByValue = array => {
const sorted = [...array].sort((a, b) => a - b);
return array.map(e => {
const i = sorted.indexOf(e);
sorted[i] = null;
return i;
})
}
console.log(...sortIndicesByValue([32, -3, 62, 8, 121, -231, 62, 13]));
console.log(...sortIndicesByValue([-1, 3, 0, 0, 2, 9, -2, 7]));

how to concat two arrays into one and remove all similar values?

I have a problem needing two arrays containing some similar values and different values. I need to concat the arrays into a new array and remove the similar values only showing the individual values. something like arr1 = [1, 44, 2, 3, 5], arr2 = [33, 1, 2, 3, 4, 5], arr3 = [], return arr3 [44, 33, 4]. I have tried a few different ways with no success, one using a nested for loop and the other using .filter(). Any thoughts on how I can solve this? Here is my code:
const arrayDiffs = (arr1, arr2) => {
let arr3 = [];
for (let i = 0; i < arr1.length; i++) {
if (arr3.indexOf(arr1[i]) === -1) {
arr3.push(arr1[1]);
}
for (let n = 0; n < arr2.length; n++) {
if (arr3.indexOf(arr2[n]) === -1) {
arr3.push(arr2[n]);
}
}
return arr3;
};
}
console.log(arrayDiffs([1, 44, 2, 3, 5], [33, 1, 2, 3, 4, 5]));
I have also tried this way:
let arr3 = [];
const arrayDiffs = (arr1, arr2) => {
arr3 = arr1.concat(arr2);
arr3 = arr3.filter(function(item, index) {
if(arr3.indexOf(item) == index){
return true;
}
return false;
});
}
console.log(arrayDiffs([1, 44, 2, 3, 5], [33, 1, 2, 3, 4, 5]));
const myFunc = (a,b) => {
const a_but_not_b = a.filter(x=>!b.includes(x));
const b_but_not_a = b.filter(x=>!a.includes(x));
return [...a_but_not_b,...b_but_not_a];
}
console.log(myFunc([1,2,3],[2,3,4]));
But, let me explain more:
Use filter and includes to get difference.
Last I concat the arrays using spread operator [...a,...b].
Using your first method only we can achieve this. You have to do the following modifications.
for (let i = 0; i < arr1.length; i++) {
if (arr2.indexOf(arr1[i]) === -1) { // first compare the value with arr2 and arr1 and push the non-available values into arr3
arr3.push(arr1[i]);
}
}
for (let n = 0; n < arr2.length; n++) {
if (arr1.indexOf(arr2[n]) === -1) { //compare the value with arr1 and arr2 and push the non-available values into arr3
arr3.push(arr2[n]);
}
}
const arrayDiffs = (arr1, arr2) => {
let arr3 = [];
for (let i = 0; i < arr1.length; i++) {
if (arr2.indexOf(arr1[i]) === -1) {
arr3.push(arr1[i]);
}
}
for (let n = 0; n < arr2.length; n++) {
if (arr1.indexOf(arr2[n]) === -1) {
arr3.push(arr2[n]);
}
}
return arr3;
}
console.log(arrayDiffs([1, 44, 2, 3, 5], [33, 1, 2, 3, 4, 5]));
Have you tried sets in javassript. I think they are used for storing only unique elements.this will bring down you complexity to O(N), where N is total number of elements in arrays. Example :
const letters = new Set()
[...arr1,...arr2].filter(e=>!(arr1.includes(e)&&arr2.includes(e)))
var arr1 = [1, 44, 2, 3, 5],
arr2 = [33, 1, 2, 3, 4, 5],
arr3 = [...arr1,...arr2]
.filter(e=>!(arr1.includes(e)&&arr2.includes(e)));
console.log(arr3);

Delete numbers below a certain number in an array

Today i'm facing a really weird problem.
I'm actually trying to delete numbers below a certain number in an array.
I have this array [1, 7, 2, 3, 90, 4, 70, 20] and I only want the numbers greater than 20 !
So I should have that in output : [90, 70]
But Instead I have this array : [7, 3, 90, 70, 20] ???
Here is my code :
function superior() {
var arr = [1, 7, 2, 3, 90, 4, 70, 20]
for (var i = 0; i < arr.length; i++) {
if (arr[i] < 20) {
arr.splice(arr.indexOf(arr[i]), 1);
} else {
break;
}
}
return arr;
}
console.log(superior());
Mutating an array while you're looping through it is always going to be tricky. If you shrink the size of the array, but don't change i, then you're can end up interacting with the wrong element of the array the next time through the loop. Also, using break will stop the loop from running entirely, and so skip the rest of the array. You may have meant to use continue, but since you're on the last line of the loop anyway, continue isn't needed.
Rather than trying to change the array and loop through it at the same time, i'd recommend creating a new array. Then you can loop through the old one unhindered:
const arr = [1, 7, 2, 3, 90, 4, 70, 20]
const newArr = []
for (const i = 0; i < arr.length; i++) {
if (arr[i] >= 20) {
newArr.push(arr[i]);
}
}
console.log(newArr)
Filtering an array like this is a very common thing to do, so there are built in tools to do it for you. Every array has a .filter method. You pass into it a function describing what elements you want to keep, and it will produce the new array for you:
const arr = [1, 7, 2, 3, 90, 4, 70, 20]
const newArr = arr.filter(element => element >= 20);
console.log(newArr)
You can filter them out according to a condition.
And replace your existing array with the filtered one. Or if you don't want to replace it, use another variable and assign the filtered value to that variable.
var newArray = array.filter(item => item > 20)
Check .filter()
var array = [1, 7, 2, 3, 90, 4, 70, 20];
array = array.filter(item => item > 20)
console.log(array)
You can use Array.filter()
var arr = [1, 7, 2, 3, 90, 4, 70, 20]
var filteredArr = arr.filter(item => item > 20);
console.log(filteredArr);
You could iterate from the end and omit indexOf, because you have already the index i.
This appoach loops from the end and after splicing, the remaining lower indices remains.
function superior() {
var array = [1, 7, 2, 3, 90, 4, 70, 20],
i = array.length;
while (i--) if (array[i] < 20) array.splice(i, 1);
return array;
}
console.log(superior());
Use temporary array to push new values.
function superior() {
var arr = [1, 7, 2, 3, 90, 4, 70, 20];
temp_arr = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i] > 20) {
temp_arr.push(arr[i]);
}
}
return temp_arr;
}
console.log(superior());

How to get multiple indexes of array by a value in pure JavaScript (value exact matching)

I'm trying to make indexOf return me multiple indexes of array's items which value equal "1" (exactly matching).
Here's what I'm doing:
var arr = [1, 11, 1, 111, 1111, 11, 1, 1111, 11];
for (i = 0; i < arr.length; i++){
console.log(arr.findIndex(1, i));
}
Result which I expect is:
0
2
6
But actually I get "-1" value after mentioned indexes. I'm assuming that it's related to array's
values (each of them include "1" but not equals to "1"). When I'm doing the same with array of
different values, it works as desired.
Does it really related to values? If yes, how to solve this problem?
If there are more proper ways to find multiple array's indexes by a value (with exact match), it would be much appreciated.
You can reduce the array to array of indexes, which value is 1:
const arr = [1, 11, 1, 111, 1111, 11, 1, 1111, 11];
const indexes = arr.reduce((r, n, i) => {
n === 1 && r.push(i);
return r;
}, []);
console.log(indexes);
You can also use indexOf and a while loop, to start search from the last found index, and stop when the index is -1:
const arr = [1, 11, 1, 111, 1111, 11, 1, 1111, 11];
let i = -1;
const indexes = [];
while(i = arr.indexOf(1, i + 1), i !== -1) indexes.push(i);
console.log(indexes);
There are multiple ways to do it with Pure JavaScript. I've added some of them.
Using Array.prototype.filter()
var arr = [1, 11, 1, 111, 1111, 11, 1, 1111, 11];
var keys = [];
var filtered = arr.filter((e, i) => {
if (e === 1) {
keys.push(i);
}
});
console.log(keys);
Using Array.prototype.forEach()
var arr = [1, 11, 1, 111, 1111, 11, 1, 1111, 11];
var keys = [];
arr.forEach((e,i)=>{
if(e === 1){
keys.push(i);
}
});
console.log(keys);
Using Array.prototype.reduce()
var arr = [1, 11, 1, 111, 1111, 11, 1, 1111, 11];
var keys = [];
arr.reduce(function(a, e, i) {
if (e === 1)
keys.push(i);
return keys;
}, [])
console.log(keys);

Add a random and not existing item to array from another array

Let's assume we have an array of items:
const arr1 = [22, 54, 67, 11, ...so on]
and empty one:
let arr2 = []
I can add random item with:
arr2 = [...arr2, arr1[Math.floor(Math.random()*arr1.length)]]
BUT how can I add a random item from first array to 2nd and already added should not be added?
Yes, we can keep added indexes in some tmp variable, but it doesnt seems right and I think there should be a different solution.
NOTE: array spreads because I need to add an item with some events.
For example user click to button and new item will be added to 2nd array, and this array may contain already added elems
You can create your custom logic to push the random value in arr2 so that the condition is that the numbers must be unique in arr2 and it will have maximum random numbers till the length of arr1:
const arr1 = [27, 54, 67, 11, 15, 22, 26, 58, 45, 87];
let arr2 = [];
function getRandom(){
var randomNumber = arr1[Math.floor(Math.random()*arr1.length)];
while(arr2.indexOf(randomNumber) !== -1 && arr2.length !== arr1.length) {
randomNumber = arr1[Math.floor(Math.random()*arr1.length)];
}
arr2.push(randomNumber);
}
getRandom(); getRandom(); getRandom(); getRandom(); getRandom(); getRandom(); getRandom(); getRandom(); getRandom(); getRandom();getRandom();
console.log(arr2);
I think you are looking for something like this:
const arr1 = [22, 54, 67, 11, 23, 56, 43, 77, 34, 76, 30]
let arr2 = []
function addRandom() {
if(new Set(arr1).size === arr2.length) return; //prevention from infinite loop
// if(arr1.length=== arr2.length) return; // if arr1 doesn't contain duplicates
let random = arr1[Math.floor(Math.random()*arr1.length)];
if (!arr2.includes(random)) {
arr2.push(random);
} else {
addRandom();
}
}
addRandom();
console.log(arr2);
addRandom();
console.log(arr2);
addRandom();
console.log(arr2);
If you are sure that arr1 wont contain duplicates then replace (new Set(arr1).size === arr2.length) with arr1.length=== arr2.length.
If this is ok to mutate arr1 (as Matt Burland suggested in comments), try this:
arr2 = [...arr2, ...arr1.splice(Math.floor(Math.random()*arr1.length), 1]);
splice will remove the item from arr1 and return you the item removed, ready to be added in arr2!
If you cannot change it, just make a clone before using this line!
Hoping this will help you :)
If compatibility is not an issue you can use array set.
var arr1 = [44, 55, 100];
var arr2 = [44, 55, 100];
var arr3 = [...new Set(arr1, arr2)];
Something like this should work
let arr1 = [22,43,67,11,63];
let indexes = [...arr1.keys()];
indexes = indexes.sort(() => Math.Random() - 0.5);
let arr2 = [];
arr2 = [...arr2, arr1[indexes.pop()]]
This lets you preserve the original order of your first array too.
You could use the include function on your second array and check if the element you are trying to add does not exists.
let randomItem = arr1[Math.floor(Math.random()*arr1.length)];
while(arra2.includes(randomItem)) {
randomItem = arr1[Math.floor(Math.random()*arr1.length)];
}
arr2.push(randomItem);
#WebArtisan, you can also try the below code.
// Function that returns a randomly selected unique list of items from another
// array with duplicated items
function getUniqueRandomItems(arr1) {
let arr2 = [];
while(arr1.length) {
// A random number in range [0, arr1.length-1]
randomIndex = Math.floor((Math.random() * (arr1.length)) + 1) - 1;
// Removing 1 item from random index in range
removedItem = arr1.splice(randomIndex, 1)[0];
// If removedItem does not exist then add it to arr1
if(arr2.indexOf(removedItem) < 0) {
arr2.push(removedItem);
}
}
return arr2 // Return the result array with unique random items
}
/************ TEST 1****************************************/
const arr1 = [22, 54, 67, 11, 54, 22, 67, 11, 88, 90, 54, 2, 3, 2, 11, 54, 0];
const arr2 = getUniqueRandomItems(arr1);
console.log(arr2); // [ 2, 22, 88, 67, 54, 11, 3, 90, 0 ]
/************ TEST 2****************************************/
const arr3 = [1, 5, 2, 5, 1, 3, 3, 6, 3, 1, 9, 8, 10, 9, 7, 4, 3, 4, 2, 1, 10];
const arr4 = getUniqueRandomItems(arr3);
console.log(arr4); // [ 1, 7, 9, 10, 5, 3, 2, 8, 4, 6 ]

Categories