Having Data in array of arrays with duplicate arrays of Oth position.
explanation
Compare arrays with its zero th position and make the result accurately.
let array = [["2018-03-09", 10, 11, 0],["2018-03-10", 100, 101, 105],["2018-03-15", 20, 0, 25],["2018-03-09", 0, 0, 15],["2018-03-15", 0, 10, 0]]
let output = [];
for (let i = 0; i < array.length; i++) {
let key = array[i][0]
let index = output.findIndex(x => x[0] == key)
if (index >= 0) {
for (let k = 1; k < array[i].length; k++) {
if (array[i][k] >= output[index][i]) {
output[index][k] = array[i][k]
} else {
output[index][k] = output[index][i]
}
}
} else {
output.push(array[i])
}
}
console.log(output)
Required Output
output=[["2018-03-09",10,11,15],["2018-03-10",100,101,105],["2018-03-15",20,10,25]]
How can I achieve this?
You could use a lookup object to find previous entries with the same values, then merge them. Array destructuring is helpful to make the code clean:
const byDate = {};
const result = [];
for(const [date, ...values] of array) {
if(byDate[date]) {
values.forEach((v, i) => byDate[date][i + 1] = Math.max(byDate[date][i + 1], v));
} else {
result.push(byDate[date] = [date, ...values]);
}
}
For better readability, you can update the array in a separate function (I kept the for loop method you used, although we could use here a forEach() call).
Here, updateEntry will look in an output array (entries argument) for an existing entry, updating it if found otherwise it will append it to the output array.
Below a working snippet.
function updateEntry(entries, entry) {
for (let i = 0; i < entries.length; i++) {
if (entry[0] != entries[i][0]) continue;
for (let j = 1; j < entry.length; j++) {
if (entry[j] >= entries[i][j])
entries[i][j] = entry[j];
}
return;
}
entries.push(entry);
}
let array = [
["2018-03-09", 10, 11, 0],
["2018-03-10", 100, 101, 105],
["2018-03-15", 20, 0, 25],
["2018-03-09", 0, 0, 15],
["2018-03-15", 0, 10, 0]
];
let output = [];
for (let i = 0; i < array.length; i++) {
updateEntry(output, array[i]);
}
console.log(output);
Use array.reduce to build an object with the identifier (the date) as the keys, which sums the other three values. Then, use Object.values to return your desired array output.
let array = [["2018-03-09", 10, 11, 0],["2018-03-10", 100, 101, 105],["2018-03-15", 20, 0, 25],["2018-03-09", 0, 0, 15],["2018-03-15", 0, 10, 0]];
let output = Object.values(array.reduce((r, e) => {
var k = e[0];
if (!r[k]) r[k] = [k, 0, 0, 0];
r[k][1] += e[1];
r[k][2] += e[2];
r[k][3] += e[3];
return r;
}, {}));
console.log(output);
Related
description :
i expect the indexPlus 2 but it comes 11,what is wrong? and why?
see it in line 28 .
code:
var inputArr = [1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0]
console.log('before', inputArr)
var arr = []
//先遍历inputArr确定0的位置
for (key in inputArr) {
if (inputArr[key] === 0) {
arr.push(key)
}
}
//将0移到数组最后面,通过位置交换实现
for (value of arr) {
for (i = value; i < inputArr.length - 1; i++) {
swap(i, i + 1)
}
}
function swap(index, indexPlus) {
var temp = inputArr[index]
inputArr[index] = inputArr[indexPlus]
inputArr[indexPlus] = temp
}
console.log('after', inputArr)
When you do for (key in inputArr), the keys are strings, not integers. So later when you do swap(i, i + 1), i is a string, and i + 1 does string concatenation, not integer addition.
Change the first loop to loop over indexes, not keys.
var inputArr = [1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0]
console.log('before', inputArr)
var arr = []
//先遍历inputArr确定0的位置
for (let key = 0; key < inputArr.length; key++) {
if (inputArr[key] === 0) {
arr.push(key)
}
}
//将0移到数组最后面,通过位置交换实现
for (value of arr) {
for (i = value; i < inputArr.length - 1; i++) {
swap(i, i + 1)
}
}
function swap(index, indexPlus) {
var temp = inputArr[index]
inputArr[index] = inputArr[indexPlus]
inputArr[indexPlus] = temp
}
console.log('after', inputArr)
When you use for ( in ), in every single loop, you will get a key(position) as a string. So when you take it and + 1 you will get result as a string.
I got this question during an interview.
I have an array that contains both negative and positive integers that are already sorted e.g.
const array = [-5, -3, 0, 2,7]
I am trying to write a function to sort the array using the absolute values of its elements. So the sorted array would be [ 0, 2, 3, 5, 7 ]
Here is my attempt
function sortArrayWithAbsoluteValue(array) {
const result = array.map(num => Math.abs(num)).sort((a,b) => a - b)
return result
}
Apparently, this works but it doesn't take advantage of the fact that the array is already sorted . Is there a better or more clever/efficient way to sort this?
the easiest solution is to introduce a new array and simply unshift it with elements from the first array
const array = [-9, -8, -5, -3, -2, 0, 2,7];
const newArray = [];
let i = 0, j = array.length - 1;
while(i <= j) {
const first = Math.abs(array[i]);
const last = Math.abs(array[j]);
if(first > last){
newArray.unshift(first)
i++;
}
else {
newArray.unshift(last)
j--;
}
}
console.log(newArray)
But this solution could be challenged by interviewers as unshift operator is slow o(n) so we can create newArray with the same size as array and then simply fill it in a similar way
const array = [-9, -8, -5, -3, -2, 0, 2,7];
const newArray = new Array(array.length);
let i = 0, j = array.length - 1, l = array.length - 1;
while(i <= j) {
const first = Math.abs(array[i]);
const last = Math.abs(array[j]);
if(first > last){
newArray[l] = first;
i++;
}
else {
newArray[l] = last;
j--;
}
l--;
}
console.log(newArray)
hope it helps!
You can let two indexes move towards eachother from either ends of the input array and based on how they compare, you copy the absolute value to the target array, filling it from end to front:
function absSorted(array) {
let result = Array(array.length);
for (let k = array.length - 1, i = 0, j = k; k >= 0; k--) {
result[k] = Math.abs(array[-array[i] < array[j] ? j-- : i++]);
}
return result;
}
const array = [-5, -3, 0, 2, 7];
console.log(absSorted(array));
You can use two iterators. One iterator starts from left and the other from right. Since the array is sorted one iterator points to the max absolute value. Store this value in a new array and iterate that iterator
const array = [-5, -3, 0, 2,7]
function f(array) {
let i = 0;
let j = array.length - 1;
const newArray = [];
while (i <= j) {
if (Math.abs(array[i]) < Math.abs(array[j])) {
newArray.push(Math.abs(array[j]));
--j;
} else {
newArray.push(Math.abs(array[i]));
++i;
}
}
return newArray;
}
console.log(f(array));
You can start at the min values with the inverted logic to get an increasing sort:
const array = [-5, -3, 0, 2, 7]
function g(array) {
let j = 0;
while (j < array.length && array[j] < 0) {
++j;
}
let i = j - 1;
const newArray = [];
while (i >= 0 && j < array.length) {
if (Math.abs(array[i]) < Math.abs(array[j])) {
newArray.push(Math.abs(array[i]));
--i;
} else {
newArray.push(Math.abs(array[j]));
++j;
}
}
if (i >= 0) {
newArray.push(...array.slice(0, i + 1).reverse().map(el => -el));
}
if (j < array.length) {
newArray.push(...array.slice(j));
}
return newArray;
}
console.log(g(array));
I converted all the numbers to the absolute value first using map
Then using a while loop, I used the indexOf and Math.min functions and the spread operator (...) to find the index of the minimum number of the array
Then I removed that from the array using splice
const array = [-5, -3, 0, 2,7];
function resort(array) {
const newArray = [];
array = array.map(i => Math.abs(i));
while (array.length) {
const minIndex = array.indexOf(Math.min(...array));
newArray.push(array.splice(minIndex, 1)[0]);
}
return newArray;
}
console.log(resort(array));
I have a task where I need to swap the index values within an array.
This is the code that I have written. I am kinda new to js, so it may be a bit off.
function swap(arr){
for(let i = 0; i = arr.length; i++){
if (arr[i] == 0){
return arr[i] + 1
}
if (arr[i]== 1){
return arr[i] - 1
}
}else{
return "only accepts 0 and 1"
}
}
console.log(swap[[1,0,0],[0,1,0],[1,1,0]])
the console.log should return [[0,1,1],[1,0,1],[0,0,1]]
Usin array.map() you can solve this problem.
This can be the possible solution:
const x = [[1,0,0],[0,1,0],[1,1,0]];
const result = x.map(el => el.map(item => item === 1 ? 0: 1))
console.log(result);
Using ES6 you could make something like this:
const swapArray = [0,1,1].map(index => !index);
Result: swapArray = [true, false, false]
This is brute force, you could do it probably with a map.
function swap(arr){
let returnArr = []
for(let i = 0; i < arr.length; i++){
let returnArr1 = []
for (let j = 0; j < arr.length; j++){
console.log(arr[i][j])
if(arr[i][j] === 0) returnArr1.push(1)
else if(arr[i][j] === 1) returnArr1.push(0)
}
returnArr.push(returnArr1)
}
return returnArr
}
swap([[1,0,0],[0,1,0],[1,1,0]])
[ [ 0, 1, 1 ], [ 1, 0, 1 ], [ 0, 0, 1 ] ]
You are probably wanting to do something like this -
function swap(arr) {
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr[i].length; j++) {
// Here we are just comparing arr[i][j]
// - if it is 1, make it 0
// - if it is 0, make it 1
arr[i][j] = (arr[i][j] ? 0 : 1);
}
}
// return the modified array
return arr;
}
let arr = [
[1, 0, 0],
[0, 1, 0],
[1, 1, 0]
]
console.log(swap(arr))
You could also use a short-hand syntax as follows -
let arr = [
[1, 0, 0],
[0, 1, 0],
[1, 1, 0]
];
// swapping 0s to 1 and 1s to 0
// The map will take each inner array and each element of that array and modify according to given condition
const swapped_arr = arr.map(inner_array => inner_array.map(el => el ? 0 : 1));
console.log(swapped_arr);
I have added comments at places to make you understand.
Hope this helps !
I have tested this code below, it works.
function swap(arr){
arr.forEach((item,index)=>{arr[index]=+!item});
return arr;
}
console.log(swap([1,0,0]));
console.log(swap([1,1,1]));
console.log(swap([1,0,1]));
Try this:
function swap(arr){
return arr.map(x => x.map(j => Number(!j)));
}
console.log(swap([[1,0,0],[0,1,0],[1,1,0]]));
Dear all I'm trying to find non repeated value in an array using javascript.I have written some code but it not working properly ..can you guys tell me where is the problem.thanks.
var arr = [-1, 2, 5, 6, 2, 9, -1, 6, 5, -1, 3];
var n = arr.length;
var result = '';
function nonrep() {
for (var i = 0; i < n; i++) {
var j;
for (j = 0; j < n; j++)
if (i != j && arr[i] == arr[j]) {
result = arr[i];
break;
}
if (j == n)
return arr[i];
}
return result;
}
console.log(nonrep())
There is possibly a more neat approach to this solution, but this works as expected by filtering the array and compare it's current value with the array items itself (expect current item's index value).
const sampleArray = [1,2,3,7,2,1,3];
const getNonDuplicatedValues = (arr) =>
arr.filter((item,index) => {
arr.splice(index,1)
const unique = !arr.includes(item)
arr.splice(index,0,item)
return unique
})
console.log("Non duplicated values: " , ...getNonDuplicatedValues(sampleArray))
Some changes:
Move all variable declarations inside of the function.
Use a function parameter for the handed over array, keep the function pure.
Declare all needed variables at top of the function in advance.
Take an array as result array unique.
Check i and j and if equal continue the (inner) loop.
Check the value at i and j and exit the (inner) loop, because a duplicate is found.
Take the check at the end of the inner loop and check the index j with the length of the array l, and if equal push the value to unique.
Use a single return statement with unique array at the end of the outer loop.
function getUnique(array) {
var l = array.length,
i, j,
unique = [];
for (i = 0; i < l; i++) {
for (j = 0; j < l; j++) {
if (i === j) {
continue;
}
if (array[i] === array[j]) {
break;
}
}
if (j === l) {
unique.push(array[i]);
}
}
return unique;
}
console.log(getUnique([-1, 2, 5, 6, 2, 9, -1, 6, 5, -1, 3]));
Another solution could be to check if indexOf and lastIndexOf returns the same value. Then you found a unique value.
var array = [-1, 2, 5, 6, 2, 9, -1, 6, 5, -1, 3],
unique = array.filter((v, i) => array.indexOf(v) === array.lastIndexOf(v));
console.log(unique);
You could first use reduce to get one object with count for each number element and then filter on Object.keys to return array of non-repeating numbers.
var arr=[-1,2,5,6,2,9,-1,6,5,-1,3];
var obj = arr.reduce((r, e) => (r[e] = (r[e] || 0) + 1, r), {});
var uniq = Object.keys(obj).filter(e => obj[e] == 1).map(Number)
console.log(uniq)
Solution with for loop.
var arr = [-1, 2, 5, 6, 2, 9, -1, 6, 5, -1, 3];
var uniq = [];
for (var i = 0; i < arr.length; i++) {
for (var j = 0; j < arr.length; j++) {
if (arr[i] == arr[j] && i != j) break;
else if (j == arr.length - 1) uniq.push(arr[i])
}
}
console.log(uniq)
Another simple approach
var arr = [1,1,2,3,3,4,4,5];
let duplicateArr = [];
var repeatorCheck = (item) => {
const currentItemCount = arr.filter(val => val=== item).length;
if(currentItemCount > 1) duplicateArr.push(item);
return currentItemCount;
}
var result = arr.filter((item,index) => {
var itemRepeaterCheck = !duplicateArr.includes(item) && repeatorCheck(item);
if(itemRepeaterCheck === 1){
return item;
}
});
console.log(result);
let arr = [1, 2, 1, 3, 3, 5];
function nonRepeatableNo(arr) {
let val = []
for (let i = 0; i < arr.length; i++) {
let count = 0;
for (let j = 0; j < arr.length; j++) {
if (arr[i] === arr[j]) {
count += 1
}
}
if (count === 1) {
val.push(arr[i])
}
}
console.log(val)
}
nonRepeatableNo(arr)
const arr = [-1, 2, 5, 6, 2, 9, -1, 6, 5, -1, 3];
const non_repeating = arr.filter(num => arr.indexOf(num) === arr.lastIndexOf(num))
console.log(non_repeating)
Filtering only unique elements according to OP request:
This uses for loops, as requested. It returns an array containing only elements appearing once in the original array.
var arr = [-1, 2, 5, 6, 2, 9, -1, 6, 5, -1, 3];
var n = arr.length;
var result = [];
function nonrep() {
for (var i = 0; i < n; i++) {
for (var j=0 ; j < n; j++)
if (i!=j && arr[i]==arr[j])
break;
if(j==n)
result.push(arr[i]);
}
return result;
}
console.log(nonrep())
var arr1 = [45, 4,16,25,45,4,16, 9,7, 16, 25];
var arr=arr1.sort();
console.log(arr);
var str=[];
arr.filter(function(value){
if( arr.indexOf(value) === arr.lastIndexOf(value))
{ str.push(value);
console.log("ntttttttttttttnnn" +str)
}// how this works ===============A
})
O/P
7,9
Please try the below code snippet.
var arr = [-1, 2, 5, 6, 2, 9, -1, 6, 5, -1, 3];
var uniqArr = [];
for (var i = 0; i < arr.length; i++) {
for (var j = 0; j < arr.length; j++) {
if (arr[i] == arr[j] && i != j) break;
else if (j == arr.length - 1){
uniqArr.push(arr[i])
}
}
}
console.log(uniqArr)
this ES6 code worked for me :
a.map(c=>a.filter(b=>c==b)).filter(e=>e.length<2).reduce((total, cur)=> total.concat(cur), [])
Here is a working method with loops.
var arr = [-1,2,5,6,2,9,-1,6,5,-1,3];
var len = arr.length;
const result = arr
.filter(value=>{
var count=0;
for(var i=0;i<len;i++)
{
if(arr[i]===value)
count++;
}
return count===1;
})
console.log(result);
const sampleArr = [-1, 2, 5, 6, 2, 9, -1, 6, 5, -1, 3];
function getUnique(arr){
const result=[]
const obj={}
for(let i=0;i<arr.length;i++){
if(!obj[arr[i]]){
obj[arr[i]]=true
result.push(arr[i])
}else{
const index= result.indexOf(arr[i])
if(index!==-1){
result.splice(result.indexOf(arr[i]),1)
}
}
}
return result
}
const uniqueArr= getUnique(sampleArr)
console.log(uniqueArr)
Here is the solution..
var x = [1,1,2,3,2,4]
var res = []
x.map(d => {
if(res.includes(d)) {
// remove value from array
res = res.filter((a) => a!=d)
} else {
// add value to array
res.push(d)
}
})
console.log(res) // [3,4]
//without using any filter also with minimum complexity
const array = [1 , 2, 3, 4, 2, 3, 1, 6, 8,1,1 ];
const unique = new Set();
const repetedTreses = new Set();
for(let i=0; i<array.length; i++) {
if(!unique.has(array[i]) && !repetedTreses.has(array[i])){
unique.add(array[i]);
}else{
repetedTreses.add(array[i]);
unique.delete(array[i]);
}
}
let uniqueElements=[...unique];
console.log(uniqueElements);
You can use filter and indexOf for that:
console.log(
[-1, 2, 5, 6, 2, 9, -1, 6, 5, -1, 3].filter((v, i, a) => a.indexOf(v, i + 1) === -1 )
);
I need help to double a list, by doing this.
10,10,20,20,30,30,40,40
I need a function that will have the above happen by having the number made in an array twice.
This is what I've tried:
function doubleList(){
var i, s,
myStringArray = [ "Hello", "World" ],
len = myStringArray.length;
for (i=0; i<len; ++i) {
if (i in myStringArray) {
s = myStringArray[i];
}
}
It's not giving me the expected results because the code can't loop the numbers I need, I tried just simply going i < 2 and doubling it, but that didn't work at all.
One way:
console.log([].concat.apply([], [10, 20, 30, 40].map(x => [x, x])))
Another way:
const list = [10, 20, 30, 40]
const doubleList = (list) => {
const res = []
for (let x of list) {
res.push(x)
res.push(x)
}
return res
}
console.log(doubleList(list))
function doubleArrayElems(array) {
let arrayLen = array.length;
for (let i = 0; i < arrayLen; i += 2) {
array.splice(i, 0, array[i]);
}
}
let arrayElem = document.getElementById('array');
let doubleArrayElem = document.getElementById('double-array');
var myArray = [10, 20, 30, 40, 50];
arrayElem.innerHTML = myArray.toString();
doubleArrayElems(myArray);
doubleArrayElem.innerHTML = myArray.toString();
Array: <p id="array"></p>
Doubled Array: <p id="double-array"></p>
Yes, but without the extras at the end with just 40 and 50
Use array#forEach to loop over it and push the element twice into a new array
function doubleArray(x) {
var tempArray = [];
x.forEach(function(item) {
tempArray.push(item);
tempArray.push(item)
})
return tempArray;
}
var m = [10, 20, 30, 40];
console.log(doubleArray(m))