javascript sort by index and then random? - javascript

I'm using lodash to sortBy index, but among the items with the same index the sorting always comes out to be the same. How do I make sure that the ordering is random if the index are identical?
This is what I have currently:
chosen = _.sortBy(chosen, function(v) {
return v.index;
});

vanillJS/ES6 one-liner:
var arr = [{index:5,v:1},{index:3,v:3},{index:3,v:6},{index:1,v:3},{index:3,v:7}]
arr = arr.sort((i1,i2)=>i1.index==i2.index?Math.random()-0.5:i1.index-i2.index)
console.log(arr)
EDIT: not-one-liner
var arr = [{index:5,v:1},{index:3,v:3},{index:3,v:6},{index:1,v:3},{index:3,v:7}]
arr = arr.sort(function(i1,i2){
if (i1.index == i2.index) return Math.random()-0.5;
else return i1.index-i2.index;
})
console.log(arr)

Related

A function that returns an array which is the intersection of two other arrays

function arraysCommon(array1, array2) {
return array1.filter(x => array2.includes(x));
}
This function does not work the way I want it to.
For instance given array1 = [1,2,3,2,1] and array2 = [5,4,3,2,1]
it returns [1,2,3,2,1], since the elements 1,2,3 are seen in both arrays.
But I want it to return [1,2,3] in that order since 1,2,3 are seen only once in array2 and are treated as seperate entities.
So pretty much the functionality should be that
Each element in the first array can map to at most one element in the second array.
Duplicated elements in each array are treated as separate entities.
the first array determines the order
I have attempted to loop through the arrays and check and compare the number of duplicates in each array but I can't seem to get the logic working correctly. Is there a different way to approach this?
I've attached an image of two Venn diagrams that might clarify the difference
Unfortunately, it gets more complicated because you need to know what numbers you have already added. In this case you need a temporary array to hold the result. We also need to track if a number exists in the array two times.
Try this:
function arraysCommon(array1, array2) {
//Copy array2 by duplicating and spreading the elements into another array.
var copyArray2 = [...array2];
//Temperary Array
var temp = [];
for (let x of array1) {
//Check if the element is in the first array and not already added to the temp array
if (copyArray2.includes(x)) {
temp.push(x);
//Remove item from copy array2 so it cannot be used anymore
copyArray2.splice(copyArray2.indexOf(x), 1);
}
}
//Return the temp array
return temp;
}
console.log(arraysCommon([1,2,3,2,1], [5,4,3,2,1]))
console.log(arraysCommon([1,2,3,2,1], [2,2,3,3,4]))
With sorting and counting this should be possible. Since you are incrementing when you find similar characters, this should be okay:
const array1= [1,4,1,1,5,9,2,7];
const array2 = [1,8,2,5,1]
const array3 = [1,2,3,2,1];
const array4 = [5,4,3,2,1,2]
const array5 = [1,2,3,2,1];
const array6 = [2,2,3,3,4]
function arraysCommon(array1, array2) {
const ans = [];
array1.sort();
array2.sort();
let j = 0;
let i = 0;
while(i<array1.length && j<array2.length){
if(array1[i] === array2[j]){
ans.push(array1[i]);
i++;
j++;
}
else if(array2[i] > array1[j]){
i++;
}
else{
j++;
}
}
console.log(ans);
}
arraysCommon(array1,array2);
arraysCommon(array3,array4);
arraysCommon(array5,array6);
this should work as you wanted!
// test 1
const array1 = [1,4,1,1,5,9,2,7];
const array2 = [1,8,2,5,1];
// test 2
const array3 = [1,2,3,2,1];
const array4 = [5,4,3,2,1];
const mapper = (array1, array2) => {
var obj = {};
array1.forEach((x, indexX) => {
array2.forEach((y, indexY) => {
if (x == y) {
if (!Object.values(obj).includes(indexX) && !obj.hasOwnProperty(indexY)) {
obj[indexY] = indexX;
return;
}
}
})
})
return Object.values(obj).sort().map(values => array1[values]);
}
console.log(mapper(array1, array2));
console.log(mapper(array3, array4));
I hope this helps. Cheers.
You can instance a new Set, wich brings only unique values and than retorn a array from this set.
Something like this:
function arraysCommon(array1, array2) {
const filtered = array1.filter(x => array2.includes(x));
const uniqueValues = new Set(filtered)
return Array.from(uniqueValues)
}

Why i can't remove other array element in javascript?

I am working with arrays now but if I remove the second element that I choose the first one that I removed keeps returning to its spot. How can I solve this?
Here is the Code:
const fruits = ['Apple', 'Banana','Lemon', 'Guava'];
const removeItem = (arr, item) => {
let newArray = [...arr];
const index = newArray.findIndex((element)=>element===item)
if(index !== -1){
newArray.splice(index, 1)
return newArray
}
}
console.log(removeItem(fruits, 'Guava'))
console.log(removeItem(fruits, 'Lemon'))
Output:
(3) ['Apple', 'Banana', 'Lemon'] //I removed Guava
(3) ['Apple', 'Banana', 'Guava'] //I removed Lemon
Your original array is a const and cannot be updated. So it is using all original values. Here is a working version that removes from the original array.
let fruits = ['Apple', 'Banana','Lemon', 'Guava'];
const removeItem = (arr, item) => {
let newArray = [...arr];
const index = newArray.findIndex((element)=>element===item)
if(index !== -1){
newArray.splice(index, 1)
fruits = newArray;
return newArray
}
}
console.log(removeItem(fruits, 'Guava'))
console.log(removeItem(fruits, 'Lemon'))
Keywords to think about: pop push remove index placeholder
I don't understand what you are trying to achieve.
Well, I never tried Guava.

Sorting string arrays based on the number present in the element

I have to sort a string array based on the number.
Example
["1.READ","10.CREATE","3.sfg","2.dfd","12.dqwe"];
Desired Result
["1.READ","2.dfd","3.sfg","10.CREATE","12.dqwe"];
My Code
var arr = ["1.READ","10.CREATE","3.sfg","2.dfd","12.dqwe"];
var arr2 = arr.map( a => a.split('.').map( n => +n+100000 ).join('.') ).sort().map( a => a.split('.').map( n => +n-100000 ).join('.') );
console.log(arr);
console.log(arr2);
You can just split and convert the first element to Number
var arr = ["1.READ", "10.CREATE", "3.sfg", "2.dfd", "12.dqwe"];
var arr2 = arr.sort((a, b) => {
return Number(a.split(".")[0]) - Number(b.split(".")[0]);
});
console.log(arr2);
The code above will also sort the first variable. If you you only want arr2 to be sorted, you can:
var arr = ["1.READ", "10.CREATE", "3.sfg", "2.dfd", "12.dqwe"];
var arr2 = [...arr]; //Spread the array so that it will not affect the original
arr2.sort((a, b) => {
return Number(a.split(".")[0]) - Number(b.split(".")[0]);
});
console.log(arr);
console.log(arr2);
You could split and take only the first part. Then take the delta for sorting.
var array = ["1.READ", "10.CREATE", "3.sfg", "2.dfd", "12.dqwe"];
array.sort((a, b) => a.split(".")[0] - b.split(".")[0]);
console.log(array);
Here it is:
var arr = ["1.READ","10.CREATE","3.sfg","2.dfd","12.dqwe"];
arr.sort(function(a, b) {
return a.split('.')[0] - b.split('.')[0];
});
console.log(arr)
// ["1.READ", "2.dfd", "3.sfg", "10.CREATE", "12.dqwe"]
This answer base on built in array sort function, with customizable compare logic.
Check this out for more detail: Javascript Array Sort
Cheers,

Integer arrays comparison

I have a question of JS arrays.
Example:
var fullArr = [1,2,3,4];
var partArr = [2,3];
var newArr = [];
We have a main array fullArr and a partial array partarr. I want to create a function/filter, which is looking for existing items in fullArr and not in partArr.
In this example above newArr must be equal to [1,4].
I've tried doing something like this, but it's not working properly.
for (var k in fullArray) { // [1,2,3,4]
for (var j in selectedArray) { // [1,4]
if (fullArray[k] == selectedArray[j]) {
newArray.splice(selectedArray[j] - 1, 1); // must be [2,3]
break;
}
}
}
What is a good way of making this? Thanks.
Here's one
var newArr = fullArr.filter(function(f) { // The filter() method creates a new array with all elements that pass the test implemented by the provided function.
return partArr.indexOf(f) == -1; // The indexOf() method returns the first index at which a given element can be found in the array, or -1 if it is not present.
})
to impress the girls, you can also
var newArr = fullArr.filter(function(f) {
return !~partArr.indexOf(f);
})
Here is the code for your requirement.
var fullArr = [1,2,3,4];
var partArr = [2,3];
var newArr = [];
for(var i=0;i<fullArr.length;i++){
if(partArr.indexOf(fullArr[i]) == -1)
newArr.push(fullArr[i]);
};
Here is the working Link
Hope it works :)
In fact, you want a common part between arrays. Obviously you can choose splice or indexOf to have O(n * m) or even O(m * n^2) performance. It's obviously suboptimal for any array larger than few elements
Or you can use objects as hash maps to find differences in (in worst case) O(n + m log m):
var fullArr = [1,2,3,4];
var partArr = [2,3];
var temporaryObject = Object.create(null);
partArr.forEach(el=>temporaryObject[el] = true); // temporaryObject after this operation is {"2": true, "3": true}
var newArr = fullArr.filter(el=>temporaryObject[el]);
In this example I have used ES6 feature called "arrow functions". It translates to following ES5 code:
var partArr = [2, 3];
var temporaryObject = Object.create(null);
partArr.forEach(function (el) {
temporaryObject[el] = true;
}); // temporaryObject after this operation is {"2": true, "3": true}
var newArr = fullArr.filter(function (el) {
return temporaryObject[el];
});
You can use the filter() function that works on arrays:
var newArr = fullArr.filter(function(val, i, arr) {
return partArr.indexOf(val) === -1;
});
This will return a new array containing the values of every iteration that returns true.
Should you ever need to do this on an object in the future a great way is to first convert the object keys to an array and then run the filter:
Object.keys(myObj).function(val, i, arr) {
return partArr.indexOf(val) === -1;
});
Here are few other approaches:
var fullArr = [1,2,3,4];
var partArr = [2,3];
var newArr = [];
1.
fullArr.map(function(element){
if(partArr.indexOf(element) === -1) newArr.push(element);
})
console.log(newArr);
2.
for(i in fullArr){
if(partArr.indexOf(fullArr[i]) === -1) newArr.push(fullArr[i]);
}
console.log(newArr);
3.
fullArr.forEach(function(element){
if(partArr.indexOf(element) === -1) newArr.push(element);
})
console.log(newArr);

Sort array in ascending order while eleminating repeated values

I'm working on project where I have array simmilar to this
var sortBp = [ 'height58em', 'width480px', 'width768px', 'width959px', 'width767px', 'width767px' ];
I want to sort this array in ascending order while eleminating repeated values so that result should be
var sortBp = [ 'height58em', 'width480px', 'width767px', 'width768px', 'width959px' ];
I'm using following function to sort array in ascending array but how do I eliminate immediate values ?? (In above case 'width767px')
var sortBp = bpArrays.sort(function(a, b) {
a = a.replace(/[a-z]/g, '');
b = b.replace(/[a-z]/g, '');
return a - b;
});
Firstly, you can't eliminate elements while sorting. You have to sort the array first, then remove duplicates. Your solution using Array.prototype.filter and Array.prototype.indexOf might be good for unsorted array, but since your array is sorted, it's overhead here(takes O(n) for each). Instead you can just loop through the array and compare element with previous one.
function uniq(array) {
var i, l = array.length, result = [];
for (i = 0; i < l; i++) {
if (result[result.length - 1] != array[i]) {
result.push(array[i]);
}
}
return result;
}
This is same with Underscore and Prototype's uniq() implemention.
Last note: remember that this will work fine with sorted array only.
If this is not homework, i.e. you aren't required to implement the algorithm yourself, you could use a combination of sortBy and uniq functions.
sortBp = [ 'height58em', 'width480px', 'width768px', 'width959px', 'width767px', 'width767px' ];
_.uniq(_.sortBy(sortBp, function(x) {return x;}), true);
This returns:
["height58em", "width480px", "width767px", "width768px", "width959px"]
Note that this will be sort by lexical order, and if you do not wish this to happen, simply substitute the identity function function(x) {return x;} with your own logic.
Array.prototype.contains = function(k) {
for ( var p in this)
if (this[p] === k)
return true;
return false;
};
inputArray.sort();
function uniqueArray(inputArray){
result=[];
for(var i in inputArray){
if(!result.contains(inputArray[i])){
result.push(inputArray[i]);
}
}
return result;
}
Found It !!
var sortBp = [ 'height58em', 'width480px', 'width768px', 'width959px', 'width767px', 'width767px' ];
uniqueArray = sortBp.filter(function(elem, pos) {
return sortBp.indexOf(elem) == pos;
});
EDIT :
I have found another solution here : http://dreaminginjavascript.wordpress.com/2008/08/22/eliminating-duplicates/
function eliminateDuplicates(arr) {
var i, len=arr.length, out=[], obj={};
for (i=0;i<len;i++) {
obj[arr[i]]=0;
}
for (i in obj) {
out.push(i);
}
return out;
}

Categories