Related
Given an array of integers, where the values should be sorted in the following order:
if we have an array
[1, -1, -3, 9, -2, -5, 4, 8,]
we must rearrange it this way: largest number, smallest number, 2nd largest number, 2nd smallest number, ...
[9, -5, 8, -3, 4, -2, 1, -1 ]
I get the first largest and smallest numbers, but can't figure out how to make it dynamic for all values in the array.
I know that I must take two variables, say firstSmallest and firstLargest and point them to the first and last index of the array respectively, run a loop, which I do already in the code below, and store value into new array by incrementing firstSmallest and decrementing firstLargest, but couldn't implement into code.
let unsortedArr = [1, 5, 8 , 7, 6, -1, -5, 4, 9, 5]
let output = [];
function meanderArray(unsorted){
let sorted = unsorted.sort((a, b) => a-b);
let firstSmallest = sorted[0];
let firstLargest = sorted[unsorted.length-1];
for(let i = 0; i <= sorted.length; i++){
//I should increment firstSmallest and decrement firstLargest numbers and store in output
}
return output;
}
meanderArray(unsortedArr);
console.log(output);
You could take a toggle object which takes the property of either the first item or last from an array and iterate until no more items are available.
function meanderArray([...array]) {
const
result = [],
toggle = { shift: 'pop', pop: 'shift' };
let fn = 'shift';
array.sort((a, b) => a - b);
while (array.length) result.push(array[fn = toggle[fn]]());
return result;
}
console.log(...meanderArray([1, 5, 8, 7, 6, -1, -5, 4, 9, 5]));
You can sort an array by descending, then logic is the following: take first from start and first from end, then second from start-second from end, etc.
let unsortedArr = [1, 5, 8 , 7, 6, -1, -5, 4, 9, 5]
let output = [];
function meanderArray(unsorted){
let sorted = unsorted.sort((a, b) => b-a);
let output = []
for(let i = 0; i < sorted.length/2; i++){
output.push(sorted[i])
if(i !== sorted.length - 1 - i){
output.push(sorted[sorted.length - 1 - i])
}
}
return output;
}
let result = meanderArray(unsortedArr);
console.log(result);
You can sort, then loop and extract the last number with pop() and extract the first number with shift().
let unsortedArr = [1, -1, -3, 9, -2, -5, 4, 8,]
let output = [];
function meanderArray(unsorted){
let sorted = unsorted.sort((a, b) => a - b);
for(let i = 0; i < unsortedArr.length + 2; i++){
output.push(sorted.pop());
output.push(sorted.shift());
}
console.log(output);
return output;
}
meanderArray(unsortedArr);
Fastest Meandering Array method among all solutions mentioned above.
According to the JSBench.me, this solution is the fastest and for your reference i have attached a screenshot below.
I got a different approach, but i found that was very close to one of above answers from elvira.genkel.
In my solution for Meandering Array, First I sorted the given array and then i tried to find the middle of the array. After that i divided sorted array in to two arrays, which are indices from 0 to middle index and other one is from middle index to full length of sorted array.
We need to make sure that first half of array's length is greater than the second array. Other wise when applying for() loop as next step newly created array will contains some undefined values. For avoiding this issue i have incremented first array length by one.
So, always it should be firstArr.length > secondArr.length.
And planned to create new array with values in meandering order. As next step I created for() loop and try to push values from beginning of the first array and from end of the second array. Make sure that dynamically created index of second array will receive only zero or positive index. Other wise you can find undefined values inside newly created Meandering Array.
Hope this solution will be helpful for everyone, who loves to do high performance coding :)
Your comments and suggestions are welcome.
const unsorted = [1, 5, 8, 7, 6, -1, -5, 4, 9, 5];
const sorted = unsorted.sort((a,b)=>a-b).reverse();
const half = Math.round(Math.floor(sorted.length/2)) + 1;
const leftArr = sorted.slice(0, half);
const rightArr = sorted.slice(half, sorted.length);
const newArr = [];
for(let i=0; i<leftArr.length; i++) {
newArr.push(leftArr[i]);
if (rightArr.length-1-i >= 0) {
newArr.push(rightArr[rightArr.length-1-i]);
}
}
let test12 = [-1, -2, -3];
I'm stuck on this one. I used the below on positive integers but I'm not sure what to change for negatives.
let test = [1 , 2, 3];
var largest= 0;
for (i=0; i<=test.length;i++){
if (test[i]>largest) {
largest=test[i];
}
}
console.log(largest);
largest negative integer in an array
Your question can have 3 interpretations:
The negative integer that is farthest from 0
The negative integer that is closest to 0
The largest number in general (you might be struggling if an all negative integer array comes along, because you initialize min to 0)
Just to clarify, smallest is 'farthest from zero'. But here's all three ways :) :
const ints = [-3, -2, -1, 0, 1, 2]
const negativeInts = ints.filter(i => i < 0)
const smallestNegative = Math.min(...negativeInts)
const largestNegative = Math.max(...negativeInts)
const largestOverall = Math.max(...ints)
console.log({smallestNegative, largestNegative, largestOverall}) // -3, -1, 2
Hope this helps. Cheers.
Just initialize largest to -Infinity rather than 0. You also need to iterate over the input array's length, not 0 to largest:
let test12 = [-1, -2, -3];
var largest = -Infinity;
for (i = 0; i < test12.length; i++) {
if (test12[i] > largest) {
var largest = test12[i];
}
}
console.log(largest);
Another method would be to spread into Math.max:
let test12 = [-1, -2, -3];
console.log(
Math.max(...test12)
);
Largest negative would be -244, so you can sort and get the first index.
let arr = [-1, -2, -244, -7],
[largets] = arr.slice().sort((a, b) => a - b);
console.log(largets);
Try this..
var array = [-155,3, 6, 2, 56, 32, 5, -89, -32,115,-150];
array.sort(function(a, b) {
return a - b;
});
console.log(array[0]);
In case you want a programming solution ,like an edit that your program needs to perform even if an all negative array is given, then try this :
let test = [-10, -1, -2, -3];
// just Assign largest to the first element in test.
// the largest int might not be greater than zero,
// but will definitely be larger that any other element in the array.
var largest= test[0];
for (i=0; i<=test.length;i++){
if (test[i]>largest) {
largest=test[i];
}
}
console.log(largest);
I have a sorted list of numbers. I want to search the array for a number (lets call it searchVal). So the line of code below works fine if the number is in the array.
var sPos = $.inArray(searchVal, MyArray);
However if it is not in MyArray I want to select the next biggest number, i.e
I'm searching for 8 in the list below I would like it to return 10.
4, 5, 6, 10, 11
I am new to javascript and wondering what the best way to achieve this is? I have seen a filter could be used where any number >= to 8 is returned and then take the min number from this filtered list. Or is this a case when I should make use of the reduce function?
You can use Array.find() on sorted array.
The find() method returns the value of the first element in the array that satisfies the provided testing function. Otherwise undefined is returned.
console.log([13, 4, 6, 5, 10, 11].sort((a, b) => a > b).find(x => x > 8));
Since the array is sorted you can use
var num = MyArray.find(x => x > 8)
For unsorted data, you could take the absolute delta of an item and check with the delta of last item and return the one with smaller delta.
var array = [5, 4, 11, 6, 10],
find = 8,
nearest = array.reduce((a, b) => Math.abs(a - find) < Math.abs(b - find) ? a : b);
console.log(nearest);
Hi you use the map function to determine the distance to 8.
var array = [4, 5, 6, 10, 11];
var distanceArray = array.map(function(element){
var distance = 8-element
if(distance < 0){
distance = distance * -1;
}
return distance;
})
then you got [4,3,2,2,3]. use Math.min
var minimum = Math.min(...distanceArray);
Now you got 2 as minimum. now found the position
var position = distanceArray.indexOf(minimum);
now you can see whats number is nearest,
var nearest = array[position];
got you 6....
I am trying to separate the negative & positive elements of an array in Javascript, such that afterwards first come all negative elements and then the positive elements, each in the original order.
Example:
Input array: [1,2,-3,-2,4]
Output array: [-3,-2,1,2,4]
Input array: [3,2,-1,0,-4,3,6,-7,-6]
Output array: [-1,-4,-7,-6,3,2,0,3,6]
I can do it using a temporary array with use of push() method, but how to do this without using a temporary array in that array only?
Use sort()
var res = [1, 2, -3, -2, 4].sort(function(a, b) {
return a - b;
});
// or just use, var res = [1, 2, -3, -2, 4].sort();
document.write(JSON.stringify(res));
For getting sorted as you like you need to add custom sorting conditions.
Update :
In your case sort() will not preserve position of same valued items, so instead you can use filter() and concat(). Using filter() get negative , zero and positive numbers in different array after that concatenate it whatever order you want using concat().
var res = [3, 4, -6, 0, -8, -1, 3, -6, 1, -8, -6, -1];
//get positive negative values
var neg = res.filter(function(v) {
return v < 0;
}),
// get positive values
pos = res.filter(function(v) {
return v > 0;
}),
// get zeros
zero = res.filter(function(v) {
return v == 0;
});
// concat result arrays
res = neg.concat(zero, pos);
document.write(JSON.stringify(res));
Same method , without using any additional variable
var res = [3, 4, -6, 0, -8, -1, 3, -6, 1, -8, -6, -1];
res = res.filter(function(v) {
return v < 0;
}).concat(res.filter(function(v) {
return v == 0;
}), res.filter(function(v) {
return v > 0;
}));
document.write(JSON.stringify(res));
When sorting by a numeric value, the basic form of the function to pass to sort is
function comparator(a, b) { return func(a) - func(b); }
Here func is a function which takes the element to be sorted, and returns the sort index to use.
To sort by "sign" (negative vs. positive), use Math.sign, which gives the sign of the element:
function sign_comparator(a, b) { return Math.sign(a) - Math.sign(b); }
array.sort(sign_comparator)
This will sort negative numbers first and positive numbers last, otherwise leaving their order unchanged (but see important note below for some browsers which may not leave the order unchanged).
a = [3,2,-1,0,-4,3,6,-7,-6]
a.sort(sign_comparator)
< [-1, -4, -7, -6, 0, 3, 2, 3, 6]
Math.sign is ES6. For platforms such as IE which do not support it, write it yourself:
function sign(x) { return x < 0 ? -1 : x > 0 ? +1 : 0; }
If you want to write your code a bit more semantically, define a generic function to create a comparator function as
function make_numeric_comparator(func) {
return function(a, b) { return func(a) - func(b); };
}
Now you can write your sort as
a.sort(make_numeric_comparator(Math.sign))
Important note on stability
In some cases, as the OP helpfully pointed out, the original order is not always preserved. This behavior is known as the stability of the sort. In simple terms, does the sort preserve the original order of pairs of items for which the sort function returns 0? It turns out that Chrome's sort is not stable, at least in some cases, which is what you are seeing. On the other hand, FF sort is stable. For details, see this SO question and this V8 issue https://code.google.com/p/v8/issues/detail?id=90. Of course, we want our sort to be stable in all browsers. So does that mean this approach will not work?
No, but it means we have to do a workaround. Here is a stable sort function:
function stable_sort(array, sortfunc) {
function _sortfunc(a, b) { return sortfunc(array[a], array[b]) || a - b; }
return array.map((e, i) => i) . sort(_sortfunc) . map(i => array[i]);
}
> stable_sort([3, 4, -6, 0, -8, -1, 3, -6, 1, -8, -6, -1], sign_comparator)
< [-6, -8, -1, -6, -8, -6, -1, 0, 3, 4, 3, 1]
What this is doing is creating a parallel array of indexes, from 1 to array.length-1, with array.map((e, i) => i). It sorts those indexes with a special sort function which calls the original sort function, but if that function returns 0 (sort in same place), it imposes the ordering of the indexes. After the array of indexes is sorted, it then uses that to look up into the original array to create the result (with the map(i => array[i])).
This may be too much work, so you may prefer another solution. On the other hand, you may want stable sorting in other contexts as well, and so if you have the stable_sort function defined, this approach would still be more straightforward than filtering out the numbers with each sign and recombining them.
for the precise requirement of seperating positive and negative number
var t = [-1,-2,-3,5,6,1]
var positiveArr = [];
var negativeArr = [];
t.forEach(function(item){
if(item<0){
negativeArr.push(item);
}
else{
positiveArr.push(item)
})
console.log(positiveArr) // output [5, 6, 1]
console.log(negativeArr) // output [-1, -2, -3]
What would be the best way to shuffle an array of numbers with the condition that each number must be +3 or -3 of the next/prev number? So, for example [0,1] wouldn't work, but [0,3] would.
Thanks!
Looking at the screenshot it seems you're wanting to pick a random assortment from the list, with no 2 choices being within 3 of each other.
This code takes an array, and gives you a subset of the array satisfying that condition.
You can specify a maximum number of selections too, although you might not always get that many.
var src = [0,1,2,3,4,5,6,7,8,9,10,11,12];
var getRnd = function(max){
var output = [];
var newSrc = src.slice();
var test, index, i, safe;
while (newSrc.length > 0 && output.length < max){
index = Math.floor(Math.random()*newSrc.length);
test = newSrc.splice(index,1);
//Make sure it's not within 3
safe = true;
for (i=0; i<output.length;i++){
if(Math.abs(test-output[i]) < 3){
//abort!
safe=false;
}
}
if(safe){
output.push(test);
}
}
return output;
};
alert(getRnd(4));
A way (likley not the fastes) would be to:
sort array
pick random element to start new shuffled array with (mark element in sorted array as used or remove)
with binary search find next element that is +3 or -3 for the last one (randomly pick between -3 and +3). Make sure element is not marked as used before (otherwise find another one)
repeat 3 till you can find elements.
you either picked all elements from sorted array or such shuffling is not possible.
I think you get O(N*logN) with this (sorting N*logN and picking N elements with logN for each serch).
Assuming that the values in the array cannot be duplicated.
function one(array, mod){
var modArray = [];
for(var index in array){
var item = array[index];
var itemMod = item%3;
if(itemMod === mod){
modArray.push(item);
}
}
return modArray();
}
function two(modArray){
var sortedArray = // sort highest to lowest
for(var index in sortedArray ){
var item = array[index];
if(index > 0 && item[index-1] === item[index]-3){
}else{return false;}
}
return sortedArray.length;
}
function main(array){
var a1 = one(array, 0);
var a2 = one(array, 1);
var a3 = one(array, 2);
var a1c = two(a1);
var a2c = two(a2);
var a3c = two(a3);
return // if a1c is greatest then a1, if a2c greatest then a2 ... etc
}
I think you must be using the phrase "shuffle" in some non-standard way. If all of the numbers are already within +-3 of each other, then sorting the array will put them in the right order, unless there are duplicates, I guess.
More examples would probably be helpful. For instance, are these examples valid, and the sort of thing you're looking for?
[0, 3, 3] -> [3, 0, 3]
[9, 3, 6, 0, 6] -> [0, 3, 6, 9, 6]
[3, 3, 6, 0, 6] -> [0, 3, 6, 3, 6]
It feels like this is probably a solved problem in graph theory - some kind of network traversal with a maximum/minimum cost function.