Make array numbers negative - javascript

I'm trying to return all array numbers as negative numbers (* -1);
I'm stuck. Please help!
function makeListNegative (array){
for(i=0; i <array.length; i++);
return i * -1;
}
var negativeList = makeListNegative([7, 2, 3, 4]);
console.log(negativeList);
This function only returns that last number in the array as -4. I would like ALL list numbers to be displayed.

You need to map the values to negative values.
function makeListNegative(array) {
return array.map(x => x * -1);
}
var negativeList = makeListNegative([7, 2, 3, 4]);
console.log(negativeList);

function makeListNegative (array) {
for (i = 0; i < array.length; i++); // 1
return i * -1; // 2
}
Your for statement iterates (in the right range with the right interval), but with the semicolon at the end of the line, it perform no operation.
Then you return the negative value of i, which is the length of the array, not a value of the array or an array with all negative values.
If you like to get you traditional approach, you could push the value in every iteration to a new array and return the new array after the iteration.
function makeListNegative(array) {
var i, l,
temp = [];
for (i = 0, l = array.length; i < l; i++) {
temp.push(-array[i]);
}
return temp;
}
var negativeList = makeListNegative([7, 2, 3, 4]);
console.log(negativeList);
You could map the negative values with Array#map.
function makeListNegative(array) {
return array.map(v => -v);
}
var negativeList = makeListNegative([7, 2, 3, 4]);
console.log(negativeList);

Your code
returned every iteration
had a semicolon in the wrong place
made the index negative instead of the array item
It could have been fixed like this
function makeListNegative(array) {
for (var i = 0; i < array.length; i++) { // make i local
array[i] *= -1; // negate the array item
}
return array; // return the manipulated array
}
var negativeList = makeListNegative([7, 2, 3, 4]);
console.log(negativeList);
Alternatively use Array.map - here in standard JS - the fat arrow => is ES6+ and does not work in IE
var negativeList = [7, 2, 3, 4].map(function(num) { return -num })
console.log(negativeList);

You can impress your senior devs by using ES6 syntax:
const makeListNegative = array => array.map(num => -num)
const negativeList = makeListNegative([7, 2, 3, 4]);
console.log(negativeList);
And if you don't want to create a function:
const negativeList = [7, 2, 3, 4].map(num => -num);
console.log(negativeList);
If you are using Babel or Typescript in your project, you don't need to worry about IE support because your code will be transpiled to ES5 and will be supported on all browsers.

This will not work as you are returning from your for loop. Try using
Array.map()

You can use map to return negative values
var negativeList= [7, 2, 3, 4].map(function(value){
return -v;
})

Since everyone solved the problem using map, here is how to solve using [forEach][1],
var makeNeg = function(arr){
arr.forEach(function(value, index){
arr[index] = arr[index]*-1;
});
return arr;
}
console.log(makeNeg([7, 2, 3, 4]))

Related

Can this selection sort implementation be made more efficient or elegant?

I have made a basic implementation of Selection sort, using Math.min() of javascript. Can anyone point out ways in which one can make this more efficient or elegant? Something that I could have avoided doing, etc? Thanks everyone, the code is below:
let arr = [2, 0, 5, 1, 3, 2, 6, 4, 9, 0, 10, 2, 14, 8];
function selectionSort(array) {
let workingArr = [...array]; //don't want to modify original array
let sortedArr = []; //this will be returned as result
for (let i = 0; i < array.length; i++) {
let sliced = workingArr.slice(0);
let min = Math.min(...sliced); //minimum of the slice
sortedArr[i] = min;
let index = workingArr.indexOf(min);
workingArr.splice(index, 1);
}
return sortedArr;
}
let x = selectionSort(arr);
console.log(x);
document.body.innerHTML = x;
I am not sure about the definition of selection sort being used here but here you have two versions of your code where: 1) you remove unnecessary copies of arrays (space inefficient) and 2) you have a more elegant solution.
Your original solution optimised
function selectionSort(array) {
const localArr = [...array];
const res = [];
for (let i = 0; i < localArr.length; i++) {
const min = Math.min(...localArr);
localArr.splice(localArr.indexOf(min), 1);
i--;
res.push(min);
}
return res;
}
Use Array.prototype.reduce
function selectionSort(array) {
const localArr = [...array];
return array.reduce((acc) => {
const min = Math.min(...localArr);
localArr.splice(localArr.indexOf(min), 1);
return acc.concat(min);
}, []);
}
Note: in your original version of the function you seemed to care about immutability. Then in the body of the function you use Array.prototype.splice and Array.prototype.push which both contravene the FP principle of immutability. I am not using a pure FP approach here just for brevity but you should look into other arrays methods that are more 'reliable' so to speak.
It seems nobody found anything here. But I finally found something that could have been avoided in original code. I figured out that there is no need to make slices of the array named workingArr in code above (in the question). Here is the modified code which is simpler.
let arr = [2, 0, 5, 1, 3, 2, 6, 4, 9, 0, 10, 2, 14, 8];
function selectionSort(array) {
let workingArr = [...array]; //don't want to modify original array
let sortedArr = []; //this will be returned as result
for (let i = 0; i < array.length; i++) {
//run upto full length of original array
let min = Math.min(...workingArr); //minimum of the slice
sortedArr[i] = min; //minimum found inserted into sortedArr
let index = workingArr.indexOf(min); //find inserted ele's position in original input array's copy, so that we can use it to removed ele from that same array (otherwise in next pass that element will still come out as min)
workingArr.splice(index, 1);
}
return sortedArr; //return resulting array
}
let x = selectionSort(arr);
console.log(x);
console.log(x.reverse()); //for descending sort

Order an unordered array of numbers from 1-8, so that the end and starting integers are alternated eg [8,1,7,2,6,3,5,4,]

I'm a newbie to all of this and trying to improve myself by solving problems and challenges.
I came across a problem whereby I have an unordered array which contains 8 integers.
eg [2,3,1,4,6,5,8,7]
I need to sort it [1,2,3,4,5,6,7,8] and reorder the array so that the array starts with the end value and then the first value and so on eg [8,1,7,2,6,3,5,4,]
I worked out I could use map() to iterate across the array and then use push() with pop() and shift() however it leaves the last 2 numbers behind in the original array and I'm not sure why. I got around this by using a concat and a reverse but I still don't understand why pop and shift don't bring across all the elements.
Code below that doesn't pull all the elements:
const reorder = (array) => {
let store = []
array.sort((a, b) => a - b).map((item, i) => {
if (array) {
store.push(array.pop())
store.push(array.shift())
}
})
return store
}
reorder([2, 3, 1, 4, 6, 5, 8, 7]) // returns [8,1,7,2,6,3]
Code that works but I have to add a concat and a reverse:
const reorder = (array) => {
let store = []
array.sort((a, b) => a - b).map((item, i) => {
if (array) {
store.push(array.pop())
store.push(array.shift())
}
})
return store.concat(array.reverse())
}
reorder([2, 3, 1, 4, 6, 5, 8, 7]) //returns [8,1,7,2,6,3,5,4]
Thanks for any help
I would just bisect the array, sort them in opposite orders and then add each element from each array to a new array
Given that you want to then take the sorted bisected arrays and produce another single array, I'd then use Array.prototype.reduce:
const alternatingSort = function (array) {
array = array.sort();
const midpoint = Math.round(array.length / 2)
let arr1 = array.slice(0, midpoint);
let arr2 = array.slice(midpoint);
arr2 = arr2.sort(function (a, b) { return b - a });
return arr1.reduce(function (retVal, item, index) {
arr2[index] && retVal.push(arr2[index]);
retVal.push(item);
return retVal;
}, []);
}
console.log(alternatingSort([2, 3, 1, 4, 6, 5, 8, 7]));
console.log(alternatingSort([2, 3, 1, 4, 6, 5, 8])); // with odd number
As I've seen nobody explained why the original OP solution doesn't work, Here is why:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/
Map calls a provided callback function once for each element in an array, in order, and constructs a new array from the results. callback is invoked only for indexes of the array which have assigned values (including undefined).
It is not called for missing elements of the array; that is:
1.Indexes that have never been set;
2.which have been deleted; or
3.which have never been assigned a value.
So what is happening in our code is that:
On the first iteration,
[(2), 3, 1, 4, 6, 5, 8, 7]
Map picks the first element(2) in the array, and delete the first and last characters in the array, so the array becomes
[3,(1), 4, 6, 5, 8]
Now, as map will not consider deleted elements, the second element(1) in the current array is called, also the first and last element in also removed:
[1, 4,(6), 5]
Now, map is trying to find the third element(6), and delete the first and last element:
[4,6]
Now, map is trying to find the fourth element, which is out of bound, so the map function will terminate.
So, you are strongly advised not to use Array.prototype.shift or Array.prototype.pop in Array.prototype.map.
You can do it following way:
const reorder = (array) => {
array.sort((a, b) => a - b);
const result = [];
const length = array.length;
for (let i = 0; i < length; i++) {
if (i % 2 === 0) {
result.push(array.pop());
} else {
result.push(array.shift());
}
}
return result;
}
const result = reorder([2, 3, 1, 4, 6, 5, 7]);
console.log(result);
Notice that I've intentionally made the array length to be an odd number. Some of the solutions here will break if the length is an odd number.
Personally I would sort, split in half and then just insert in. Not very fancy, but gets the job done.
function strangeWeave (arr) {
var sorted = arr.slice().sort()
var result = sorted.splice(0,Math.floor(sorted.length/2))
for (let i=0;sorted.length;i+=2) {
result.splice(i,0,sorted.pop())
}
return result
}
console.log(strangeWeave([1,2]))
console.log(strangeWeave([1,2,3]))
console.log(strangeWeave([1,2,3,4,5,6,7,8]))
console.log(strangeWeave([1,2,3,4,5,6,7,8,9]))
There is a much easier solution to sort two different arrays, one normal and one in reverse, then connect them together. Here is the code for that:
var myArray = [1, 3, 2, 4, 5, 7, 6, 8];
function getCopy(arr) {
var x = [];
for(var i = 0; i < arr.length; i++)
x.push(arr[i]);
return x;
}
function sortMyWay(arr) {
var sortedArr = [],
leftSide = getCopy(arr).sort()
.splice(0, Math.ceil(arr.length / 2)),
rightSide = getCopy(arr).sort().reverse()
.splice(0, Math.floor(arr.length / 2));
for(var i = 0; i < arr.length; i++)
i % 2
? sortedArr.push(leftSide[Math.floor(i / 2)])
: sortedArr.push(rightSide[Math.floor(i / 2)]);
console.log(sortedArr);
return sortedArr;
}
var sortedArr = sortMyWay(myArray);
Hope it helped!
Happy coding :)

Find 2nd largest value in an array that has duplicates of the largest integer

I'm trying to find the second largest number in an array of numbers, but the greatest number appears twice, so I can't just remove it from the array and select the new highest number.
array = [0, 3, 2, 5, 5] (therefore 3 is the 2nd largest value)
I have this code where I can explicitly return 3, but it wouldn't work on other arrays:
function getSecondLargest(nums) {
var sorted_array = nums.sort(function (a,b) {return a - b;});
var unique_sorted_array = sorted_array.filter(function(elem, index, self) {
return index === self.indexOf(elem);
})
return unique_sorted_array[unique_sorted_array.length - 2];
}
return unique_sorted_array[unique_sorted_array.length - 2];
If I wanted to make it more dynamic, is there a way that I could identify the greatest value of the array, then compare that against each iteration of the array?
I was thinking that something along the lines of:
var greatestNum = sortedArray[-1]
while(greatestNum != i) do {
//check for the first number that doesn't equal greatestNum
}
Any help would be appreciated.
You can simply create a Set first and than sort in descending and take the 1st index element
let array = [0, 3, 2, 5, 5]
let op = [...new Set(array)].sort((a,b) => b-a)[1]
console.log(op)
For those who thinks in terms of efficiency. this is the best way IMO
let array = [0, 3, 2, 5, 5]
let max = -Infinity
let secondMax = -Infinity
for(let i=0; i<array.length; i++){
if(array[i] > max){
secondMax = max
max = array[i]
}
}
console.log(secondMax)
I’d recommend doing something more like
const nums = [0, 3, 2, 5, 5];
nums.sort(function (a,b) {return b - a;})
for (let i = 1; i < nums.length; i++) {
if (nums[0] !== nums[i]) {
return nums[i];
}
}
which should be a lot more efficient (especially in terms of memory) than converting to a set and back...
Try this:
var intArray = stringArray.map(nums); // now let's sort and take the second element :
var second = intArray.sort(function(a,b){return b-a})[1];
};
For those who wants to do this using Math.max(). Here's the simplest way to do this.
const getSecondLargest = function (arr) {
const largest = Math.max.apply(null, arr);
for (let i = 0; i < arr.length; i++) {
if (largest === arr[i]) {
arr[i] = -Infinity;
}
}
return Math.max.apply(null, arr);
};
console.log(getSecondLargest([3, 5, 9, 9, 9])); //5
Side note: Math.max() don't take an array, so we have to use Math.max.apply() to pass the array in the function. -Infinity is smaller than any negative finite number.

Is it possible to use array.splice(argument[i], x) to edit an array for variables that meet a condition?

Key Question
-How do you use splice(argument[i], x)? Can it be used this way or am I only allowed to use numbers? ie (1, 2), (3, 0)
-I'm a little unsure of when element[i] can be used when an array is declared. So it can be used for both for loops and while loops when setting conditions? Can it be used as an argument or parameter in functions or additional methods besides splice?
What I want to do
-Write a function called "isEven".
-Given an array of numbers, "isEven" returns a new array.
-Only even numbers are outputted from the input array.
ex.
var output = isEven([1, 4, 5, 6, 10, 13]);
console.log(output); // --> [4, 6, 10]
Approach
-declare var digits to "catch" the array input.
-declare var NewArray for return of output array,
-use if condition to go through var digits and splice the variable at any given index.
-declare NewArray to the newly spliced array
function isEven(num) {
var digits = num;
var newArray = [];
digits.forEach(function(num) {
if (num[i] % 2 > 0) {
newArray = digits.splice(num[i], 1);
}
}) return newArray;
}
var ledoit = isEven([1, 4, 6]);
console.log(ledoit);
Try this:
function isEven(myArray) {
return myArray.filter(item => {
return Number.isInteger(item / 2)
})
}
Then isEven([1, 4, 5, 6, 10, 13]) will output [4,6,10]
You want to use the % operator:
var nums = [1, 4, 5, 6, 10, 13];
function getEvens(array){
for(var i=0,n,a=[],l=array.length; i<l; i++){
n = array[i];
if(n % 2 === 0)a.push(n);
}
return a;
}
console.log(getEvens(nums));
Albeit, not backward compatible, you could also do:
var nums = [1, 4, 5, 6, 10, 13];
function getEvens(array){
return array.filter(n => (n % 2 === 0));
}
console.log(getEvens(nums));

How to 'double' numbers in an array, and save it in a new array

This is a 2 step problem:
1.) I am trying to 'double' the contents of one array (original Array), save it in a new array (Doubled Array).
2.) Then assign those two arrays to an Object with 2 attributes.
New Object
Orginal Numbers
Doubled Numbers
This is what I have so far, what am I doing wrong?
var numbers = [8, 12, 5, 2, 5, 7];
var doubledNumbers = [];
function doubled(arr){
for (var i = 0; i < arr.length; i ++){
var dub = arr[i];
var dubb = dub*2;
doubledNumbers.push(dubb);
}
}
var collectionNumbers = {
orginialNumbers: numbers,
doubledNumbers: doubled(numbers)
};
console.log(collectionNumbers);
The best way to do this in Javascript is using the map function:
var doubledNumbers = numbers.map(n => n*2);
The argument to map is the function that it uses to transform the elements in the first array into the elements in the second array. It is a tremendously useful method.
To answer your original question, the reason you were seeing undefined in collectionNumbers is because you forgot to return doubledNumbers in your function (and functions by default return undefined.
var numbers = [8, 12, 5, 2, 5, 7];
var doubledNumbers = [];
function doubled(arr){
var doubledNumbers = [];
for (var i = 0; i < arr.length; i ++){
var dub = arr[i];
var dubb = dub*2;
doubledNumbers.push(dubb);
}
return doubledNumbers;
}
var collectionNumbers = {
orginialNumbers: numbers,
doubledNumbers: doubled(numbers)
};
console.log(collectionNumbers);
What's wrong with your current code, is that your doubled function is returning nothing (which means it's returning undefined).
A better function would look like this:
function doubled (arr) {
var doubled = [];
for (var i = 0; i < arr.length; i++) {
doubled.push(arr[i] * 2);
}
return doubled;
}
However, an even better solution would be to just do this:
var collectionNumbers = {
orginialNumbers: numbers,
doubledNumbers: numbers.map(function (n) { return n * 2; })
};
.map is awesome.
Your whole routine can be simplified to
var numbers = [8, 12, 5, 2, 5, 7];
var collectionNumbers = {
orginialNumbers: numbers,
doubledNumbers: numbers.map(function(n) { return n*2; })
};
console.log(collectionNumbers);
using Array.map to create a new array with the doubled numbers
using Array.from, you can double and return new array
let inputArray = [9,8,7,3,2]
let outputArray = Array.from(inputArray, x => x *2) // creates new array
console.log(outputArray)

Categories