Trying to sort array without sort() in JavaScript - javascript

// sorting an array
const least_num = (arr)=>{
let smallest = arr[0];
let smallest_index = 0;
for(let i=1; i<arr.length;i++){
if (arr[i] < smallest) {
smallest = arr[i];
smallest_index = i;
}
}
return smallest_index
}
const sortArray = (arr)=>{
const newArr = [];
for(let i in arr){
let smallest = least_num(arr);
console.log(smallest,i)
console.log(arr.splice(smallest,1),arr)
}
return newArr;
}
console.log(sortArray([5,4,3,2,1]));
I am trying to sort array without sort().
It stuck at array length of 2.
It may because of for loop. And how to remove element in a array using index.

A few issues:
The code never adds anything to newArr, so the function always returns an empty array. It should add the removed (spliced) element to newArr. This can be done with newArr.push(...arr.splice(smallest,1))
The for..in loop will iterate fewer times than expected, because in each iteration the array gets shorter, thereby removing future iterations for the loop. As the idea is to remove all items from the array, just keep looping until the array is empty with while (arr.length)
With these two corrections, your code works:
const least_num = (arr)=>{
let smallest = arr[0];
let smallest_index = 0;
for(let i=1; i<arr.length;i++){
if (arr[i] < smallest) {
smallest = arr[i];
smallest_index = i;
}
}
return smallest_index
}
const sortArray = (arr)=>{
const newArr = [];
while(arr.length) {
let smallest = least_num(arr);
console.log(smallest)
newArr.push(...arr.splice(smallest,1));
console.log(arr)
}
return newArr;
}
console.log(sortArray([5,4,3,2,1]));

You can also try this.
const sortArray = (arr)=>{
let originalArr = [...arr];
var sortArr = [];
while(originalArr.length) {
let val = originalArr[0];
for ( let j = 1; j < originalArr.length; j++ ) {
if(val>originalArr[j]) {
val = originalArr[j];
}
}
sortArr.push(originalArr.splice(originalArr.indexOf(val), 1)[0]);
}
return sortArr;
}
console.log(sortArray([5,4,3,2,1]));

Related

Two Arrays: Find items that are missing in the first, find items that are missing in the second

Imagine two arrays:
const array1 = [1,2,3];
const array2 = [2,3,4];
Now, I want to get all the differences of these two arrays and put them in two new arrays.
One Array will be for all the items that where missing in the first.
The other will be for the items missing in the second.
The result would look something like this:
const newArray1 = [1];
const newArray2 = [4];
How would I go about this and what is the most efficient way?
const array1 = [2,1,3,5,2,1,3,5];
const array2 = [4,3,2,6,7,4,3,2,6,7];
function diff(arr1, arr2) {
const dontAddDuplicates = true;
arr1.sort();
arr2.sort();
let a1 = [];
let a2 = [];
let i = 0;
let j = 0;
while (i < array1.length || j < array2.length) {
if (i >= arr1.length) {
if (!dontAddDuplicates || (a2.length == 0 || a2[a2.length - 1] != arr2[j])) {
a2.push(arr2[j]);
}
j++;
} else if (j >= array2.length) {
if (!dontAddDuplicates || (a1.length == 0 || a1[a1.length - 1] != arr1[i])) {
a1.push(arr1[i]);
}
i++;
} else if (arr1[i] < arr2[j]) {
if (!dontAddDuplicates || (a1.length == 0 || a1[a1.length - 1] != arr1[i])) {
a1.push(arr1[i]);
}
i++;
} else if (arr2[j] < arr1[i]) {
if (!dontAddDuplicates || (a2.length == 0 || a2[a2.length - 1] != arr2[j])) {
a2.push(arr2[j]);
}
j++;
} else {
// Same value, do nothing
i++;
j++;
}
}
return [a1, a2];
}
console.log(diff(array1, array2));
// OUTPUT: [[1, 5], [4, 6, 7]]
Here's another potential implementation using sorting, but it has the side effect of leaving array1 and array2 in a sorted fashion. Sorting allows you to avoid needing to rescan the other array every time. If they are already sorted then great you can skip this step. If the side effect is a problem, then use a deep copy of array1 and array2 before calling sort.
Flip dontAddDuplicates if you want duplicates or not. I notice the other implementations don't account for that, but easy enough to add.
Run time should be: SORT N + SORT M + N + M = SORT N = N LOG N depending on your input sizes and distributions SORT will be the significant O Notation https://www.bigocheatsheet.com/
https://jsfiddle.net/buscgtL2/1/
If you want to do it in N + M + N + M = N time you can use this implementation which uses a hash map instead of sorting. This has a disadvantage on memory space.
const array1 = [2,1,3,5,2,1,3,5];
const array2 = [4,3,2,6,7,4,3,2,6,7];
function diff(arr1, arr2) {
let dontAddDuplicates = true;
let a1 = [];
let a2 = [];
let a1hash = {};
let a2hash = {};
for (let i = 0; i < arr1.length; i++) {
a1hash[arr1[i]] = 0;
}
for (let i = 0; i < arr2.length; i++) {
a2hash[arr2[i]] = 0;
}
for (let i = 0; i < arr1.length; i++) {
if (!a2hash.hasOwnProperty(arr1[i])) {
if (!dontAddDuplicates || a1hash[arr1[i]] == 0) {
a1hash[arr1[i]] = 1;
a1.push(arr1[i]);
}
}
}
for (let i = 0; i < arr2.length; i++) {
if (!a1hash.hasOwnProperty(arr2[i])) {
if (!dontAddDuplicates || a2hash[arr2[i]] == 0) {
a2hash[arr2[i]] = 1;
a2.push(arr2[i]);
}
}
}
return [a1, a2];
}
console.log(diff(array1, array2));
//OUTPUT: [[1, 5], [4, 6, 7]]
https://jsfiddle.net/2945y3an/1/
The worse performance would be any algorithm where for every N element you scan array M searching for a match. This would be N * M = N^2
You can achieve it in very simple way with minimum line of codes by using Array.filter() along with Array.includes() methods of JavaScript.
Working Demo :
const array1 = [1,2,3];
const array2 = [2,3,4];
const updatedArray1 = array1.filter(item => !array2.includes(item));
const updatedArray2 = array2.filter(item => !array1.includes(item));
console.log(updatedArray1); // [1]
console.log(updatedArray2); // [4]
Something like this would be relatively efficient, you're only iterating through two arrays.
Iterate through the first array and add any missing items to the first newArray. Repeat the same process for the second array.
If you need to only loop through the array once, you would need to do something similar to what is done below, but only loop through the longest array.
const array1 = [1,2,3];
const array2 = [2,3];
function diff (arr1, arr2) {
const newA1 = [];
const newA2 = [];
arr1.forEach((item, i) => {
let index = arr2.findIndex(it => it === item);
if(index < 0) newA1.push(item);
});
arr2.forEach((item, i) => {
let index = arr1.findIndex(it => it === item);
if(index < 0) newA2.push(item);
});
return [newA1, newA2];
}
console.log(diff(array1, array2));
More efficent method (only loop through 1 array). This way you choose the longest array, loop through it, and check for duplicates of the current item of the long array and if an item in the secondary array exists at the same position, check for duplicates of this item in the longest array as well. This method is similar to the method above, but there is only 1 for each loop.
const array1 = [1,2,3];
const array2 = [3,4,5];
function diff (arr1, arr2) {
const newA1 = [];
const newA2 = [];
let baseArr, secondaryArr;
if(arr1.length > arr2.length) {
baseArr = arr1;
secondaryArr = arr2;
} else {
baseArr = arr2;
secondaryArr = arr1;
}
baseArr.forEach((item, i) => {
const secondaryArrI = secondaryArr.findIndex(it => it === item);
if(secondaryArrI < 0) newA1.push(item)
if(typeof secondaryArr[i] !== "undefined") {
const removeI = baseArr.findIndex(it => it === secondaryArr[i]);
if(removeI < 0) newA2.push(secondaryArr[i]);
}
})
return [newA1, newA2];
}
console.log(diff(array1, array2));
Lodash difference if you dot't mind
const array1 = [1,2,3];
const array2 = [2,3,4];
console.log(_.difference(array1, array2));
console.log(_.difference(array2, array1));
.as-console-wrapper{min-height: 100%!important; top: 0}
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.21/lodash.min.js"></script>

Replicate array to certain length in javascript

I have this array [1,2,3]
I would like to be able to set its length to 7
and have this [1,2,3,1,2,3,1] as a result.
Anyone?
const arr = [1,2,3];
// Something like
arr.resize(7);
console.log(arr); // [1,2,3,1,2,3,1]
EDIT:
Based on chevybow answer below i wrote this functions to serve my needs.
// Immutable
Array.prototype.resize = function(size) {
const array = Array(size);
for(let i = 0; i < size; i++) {
array[i] = this[i%this.length];
}
return array;
}
// Mutable
Array.prototype.resize = function(size) {
const array = this.slice(0);
this.length = size;
for(let i = 0; i < size; i++) {
this[i] = array[i%array.length];
}
}
Are those ok? or you think that putting it on the chain is not a good idea, if so why?
You can use modular arithmetic to loop through up to the length of your final array and then use the index to basically loop through and push that onto a new array
Using the current array value % array.length will get you the current position of the array by progressing it in a circular motion
let num = 7;
let array = [1,2,3];
let result = [];
for(let i = 0; i < num; i++){
result.push(array[i%array.length]);
}
console.log(result)
A simple while loop would suffice:
function repeat(arr, toLength) {
let output = [...arr];
while (output.length < toLength) output = [...output, ...arr];
return output.slice(0, toLength);
}
console.log(repeat([1, 2, 3], 7));
console.log(repeat([1, 2, 3], 2));
How about this version:
const nums = [1, 2, 3];
function resize(arr, length) {
let position = 0;
return Array.from(Array(length)).reduce((acc, _, i) => {
return acc.concat(arr[i % arr.length]);
}, []);
}
console.log(resize(nums, 7));

Insert value multiple times into array based on argument passed

I have a array like this:
var oldArr = [2,3,4,2,3,5,6,4,2,3,2];
var newArr = [];
I am passing a argument(number) to a function which should insert values from oldArr into newArr taking the argument as length for each element found in old array.
function getNumbers(num){
console.log('value passed is ', num);
for(var i=0; i<arr.length;i++){
newArr.push(arr[i]);
}
console.log('newArr', newArr);
}
getNumbers(2);
For example,
if I pass number 2 as in getNumbers(2);
new array output should be:
[2,2,3,3,4,4,5,5,6,6] //as the argument/length passed is 2.
if I pass number 3 as in getNumbers(3);
[2,2,2,3,3,3,4,4,4,5,5,5,6,6,6] //as the argument/length passed is 3.
How do I achieve this?
Try this
var oldArr = [2,3,4,2,3,5,6,4,2,3,2];
function getNumbers(arr, num){
return Array.from(new Set(arr))
.map((e) => new Array(num).fill().map(v => e))
.reduce((a, b) => a.concat(b),[]);
}
console.log(getNumbers(oldArr, 2));
console.log(getNumbers(oldArr, 3));
First of all, you need to get the unique values from the array. That's the Array.from(new Set(arr));.
Secondly, we can allocate new array for each number (to be able to nicely flatten it later). That's what new Array(num).fill().map(v => e)) does. Result of this will be like [[2,2],[3,3],[4,4]..] etc.
And lastly, flatten it all using Array.prototype.reduce.
var oldArr = [2,3,4,2,3,5,6,4,2,3,2];
var uniqueArr = oldArr.filter(function(elem, index, self) {
return index == self.indexOf(elem);
})
console.log(uniqueArr)
function getNumbers(num){
var newArr = [];
for(var i=0; i<uniqueArr.length;i++){
for(var j=0;j<num;j++)
newArr.push(uniqueArr[i]);
}
console.log('newArr', newArr);
}
getNumbers(2);
getNumbers(3);
Remove all your duplicates from your old array using Array#Filter , then loop through all element and store it in new array.
The following function should work
function duplicateN(oldArray, newArray, N) {
for (var i = 0; i < oldArray.length; i++) {
for (var j = 0; j < N; j++) {
newArray.push(oldArray[i]);
}
}
}
It simply iterates over each value in the original array and then inserts it N times.
I'm not sure the usage of this, but if newArray is always empty, something like this would be more maintainable
function duplicateN(inputArray, N) {
var duplicatedArray = [];
for (var i = 0; i < inputArray.length; i++) {
for (var j = 0; j < N; j++) {
duplicatedArray.push(inputArray[i]);
}
}
return duplicatedArray;
}
var arr = [2,3,4,5];
function getNumbers(num){
var j = 1;
var newArr = [];
for(var i=0; i<arr.length;i++)
{
j = 1;
while(j<=num){
newArr.push(arr[i]);
j++;
}
}
console.log(newArr.join());
}
getNumbers(4);
let multiply_array = (arr, mi = 1) =>
[].concat.apply([], arr.filter((i, ind) =>
arr.indexOf(i) == ind).map(i =>
Array(mi).fill(i)));
The multiply_array function takes two parameters, an array and the multiplying integer. It filters through the array and finds all unique values by comparing position. It then maps over all the remaining unique integers and replaces them with an array that is the length specified by the passed in multiplying integer, and filled with the unique value. All of it is concatenated together to form one array.
var oldArr = [2, 3, 4, 2, 3, 5, 6, 4, 2, 3, 2];
var newArr = [];
let multiply_array = (arr, mi = 1) =>
[].concat.apply([], arr.filter((i, ind) =>
arr.indexOf(i) == ind).map(i =>
Array(mi).fill(i)));
console.log(multiply_array(oldArr, 3));
You can do this using chain of Array.prototype methods:
var oldArr = [2,3,4,2,3,5,6,4,2,3,2];
function getNumbers(num){
return oldArr
.filter((elem, index, arr) => !arr.slice(index + 1).includes(elem))
.sort((prev, next) => next < prev)
.reduce((result, elem) => result.concat(Array(num).fill(elem)), [])
}
console.log(getNumbers(2));
console.log(getNumbers(3));

JS delete duplicated items from array without higher order functions

I know it's a stupid question, but I only learning programming 3 months now.
How would you solve this problem, if you can't use higher order functions and built-in methods, like filter or indexOf?
Create a function that takes a list of numbers and returns a new list where all the duplicate values are removed
I got this so far, but I think It's a dead end...
const array = [1, 2, 3, 3, 1];
const removeDuplicate = () => {
let shortArray = [];
let index = 0;
for (let i = 0; i < array.length; i++) {
for (let j = 0; j < array.length; j++) {
if (i != j) {
if (array[i] == array[j]) {
shortArray[index] += array[i]
console.log(array[i]);
}
}
}
}
return shortArray;
}
console.log(removeDuplicate());
return this:
1
3
3
1
[ NaN ]
thanks!
Use an object as a helper. If a value appears in the helper, it's not unique and can be ignored. If it's not in the helper it's unique, push it into the result array, and add it to the helper object.
const array = [1, 2, 3, 3, 1];
const removeDuplicate = (arr) => {
const helperMap = {};
const result = [];
for (let i = 0; i < arr.length; i++) {
const item = arr[i];
if (!helperMap[item]) {
result[result.length] = item;
helperMap[item] = true;
}
}
return result;
};
console.log(removeDuplicate(array));
function unique(arr) {
var obj = {};
for (var i = 0; i < arr.length; i++) {
var value = arr[i];
obj[value] = true; // set as key
}
return Object.keys(obj); //return all keys
}
Use below function:
function RemoveDuplicate(array){
let shortArray = [];
let index = 0;
for (let i = 0; i < array.length; i++) {
let exist=false;
for(let j=0;j<shortArray.length;j++){
if(array[i]==shortArray[j]){
exist=true;
break;
}
}
if(!exist){
shortArray[shortArray.length]=array[i];
}
}
return shortArray;
}

Understanding For loops in javascript - printing index of values in Array

I'm trying to print the indexes of values of an array. When I do this:
let a = [1,2,3,4,5];
var findIdx = function (arr) {
for (let i = 0 ; i < arr.length; i++) {
var indexes = [];
var index = arr[i];
console.log(index);
return indexes.push(index);
}
return indexes;
}
console.log(findIdx(a));
// => 0,1 // return
Which is not what I want, I would like to get the index of those values. Furthermore, my return is returning 1. I would like an array made of those indexes. What am I missing?
When I do a for in loop I get what I want on my console, but I'm still returning the value where that index is found.
let a = [1,2,3,4,5];
var findIdxWithForIn = function (arr) {
var indexes = [];
for (i in arr) {
var index = i;
console.log(index);
return indexes.push(index);
}
return indexes
}
console.log(findIdxWithForIn(a));
// => 0, 1 // return
TL;DR: Here is a jsfiddle with the above code.
Note that I would like just to all the indexes inside that array
You are printing var index which is not an index it is element in array:
var index = arr[i];
console.log(index);
You need to get index so var index = i;. Because i in for loop is actual index. You can also use arr.indexOf(...); to get index of specific element.
You should do something like this,
var findIdxWithForIn = function (arr) {
var indexes = [];
for (i in arr) {
var index = i;
indexes.push(index)
console.log(index);
}
return indexes;
}
Now in case you want to find out what the indexes array contains then again you have put that in a for loop and extract
indexes.push(index) Should be inside for loop. You were doing it wrong.
var findIdxWithForIn = function (arr) {
var indexes = [];
for (i in arr) {
var index = i;
indexes.push(index)
}
return indexes;
}
console.log(findIdxWithForIn(a));
Try this out
let a = [1, 2, 3, 4, 5];
console.log('======= For Loop ========')
/*
For loop
*/
var findIdx = function (arr) {
var indexes = [];
for (let i = 0 ; i < arr.length; i++) {
var index = arr[i];
console.log(index);
indexes.push(index);
}
return indexes
}
console.log(findIdx(a));
console.log('======= For In ========')
/*
For In Loop
*/
var findIdxWithForIn = function (arr) {
var indexes = [];
for (i in arr) {
var index = i;
console.log(index);
indexes.push(index);
}
return indexes //.push(index);
}
console.log(findIdxWithForIn(a));

Categories