I Javascript I have an array of dates, for example:
["2018-04-25",
"2018-04-25",
"2018-04-26",
"2018-04-27",
"2018-04-28",
"2018-04-28"]
How can I recognise duplicate dates and change them to false so the values become:
["2018-04-25",
false,
"2018-04-26",
"2018-04-27",
"2018-04-28",
false]
This is what it needs to be.
Thanks
With a sorted array, you could check the predecessor and return false if the same, otherwide the value.
var array = ["2018-04-25", "2018-04-25", "2018-04-26", "2018-04-27", "2018-04-28", "2018-04-28"];
array = array.map((v, i, a) => a[i - 1] !== v && v);
console.log(array);
For unsorted arrays and respecting the first same date, as mentioned by Kevin Hoerr in the comments, take indexOf and check against the actual index.
var array = ["2018-04-25", "2018-04-25", "2018-04-26", "2018-04-27", "2018-04-28", "2018-04-28"];
array = array.map((v, i, a) => a.indexOf(v) === i && v);
console.log(array);
If you have a complete ISO date, you could use just the date without time. This approach needs sorted data.
var array = ['2018-04-14T13:00:00+02:00', '2018-04-15T08:45:00+02:00', '2018-04-15T10:00:00+02:00', '2018-04-22T08:45:00+02:00', '2018-04-22T10:00:00+02:00', '2018-04-29T08:45:00+02:00', '2018-04-29T10:00:00+02:00'];
array = array.map((v, i, a) => (a[i - 1] || '').slice(0, 10) !== v.slice(0, 10) && v);
console.log(array);
forEach seems to be easier to read than the map and reduce I see here
var data = ["2018-04-25","2018-04-25","2018-04-26","2018-04-27","2018-04-28","2018-04-28"];
var newArr = [];
data.forEach(function(x) {
newArr.push(newArr.includes(x) ? false : x)
});
console.log(newArr)
Related
var merge = function(nums1, m, nums2, n) {
//contcating two array
let array = nums2.concat(nums1)
// sort the array
array.sort((a,b) => a-b)
// remove element > m+n length
return array.slice(m+n-n)
};
This ^ function is returning -> [1,2,3,0,0,0]
if i'm applying console then answer is same as expected -> [1,2,2,3,5,6]
Why is this happening ?
Remove slice function from the end of the function.
slice(m+n-n) slices your sorted array and returns array from index m+1 to the last index.
var merge = function(nums1, m, nums2, n) {
//contcating two array
let array = nums2.concat(nums1)
// sort the array
array.sort((a,b) => a-b)
// remove element > m+n length
return array.slice(m+n-n);
};
console.log(merge([2,4,8,9],4,[0,4,6,9],4));
You can use the following function to merge and then sort the two arrays.
Time complexity of this approach is O(nlogn)
function merge(arr1,arr2){
return [...arr1,...arr2].sort();
}
console.log(merge([4,8,6],[1,3,9,10]));
The second approach runs in O(n) time.
function merge(arr1,m,arr2,n){
let result = [];
let i=0 , j = 0 ;
while(i<m && j<n){
if(arr1[i]<arr2[j]){
result.push(arr1[i]);
i++;
}else{
result.push(arr2[j]);
j++;
}
}
while(i<m){
result.push(arr1[i]);
i++;
}
while(j<n){
result.push(arr2[j]);
j++;
}
return result;
}
console.log(merge([4,5,6],3,[1,3,8,10],4));
I did not see any problem with your code and it works, I just added another code. I think the problem with your console.log.
var merge = function(nums1, m, nums2, n) {
//contcating two array
let array = nums2.concat(nums1)
// sort the array
array.sort((a,b) => a-b)
// remove element > m+n length
return array.slice(m+n-n)
};
console.log(merge([1,2,3,0,0,0],3,[2,5,6],3));
var merge = function(nums1, m, nums2, n) {
return nums1.slice(0, m)
.concat(nums2.slice(0, n))
.sort((i, j) => i - j);
};
console.log( merge([1,2,3,0,0,0],3,[2,5,6],3))
I'm trying to get the indexes of 'all' the highest values in an array:
[0,1,4,3,4]
Need to get back [2,4] as a result.
Update: Thanks everyone for the quick responses. After reading some of the earlier comments, it spawned this path for me:
var array = [0,1,4,3,4];
var indexes = [];
var highest = Math.max(...array);
array.forEach(function(element, i) {
if (element == highest) {
indexes.push(i);
}
});
I know it's a bit verbose, but it makes sense to me. I better read up on 'reduce'.
Using Math.max you can get the maximum element. Post that you map over the array and get the indices of this max element. The complexity of this approach is O(n);
const arr = [0,1,4,3,4];
const max = Math.max(...arr);
const res = [];
arr.forEach((item, index) => item === max ? res.push(index): null);
console.log(res);
Here idea is
First find the max value using math.max
Now loop through the array and add the index if the value is same as max
let arr = [0,1,4,3,4]
let max = Math.max(...arr)
let op = []
for(let i=0; i<arr.length; i++){
if(arr[i] === max){
op.push(i)
}
}
console.log(op)
One alternate way of doing is using reduce and a variable to keep track of max value and than access the max key's value
let arr = [0,1,4,3,4]
let max = null
let op = arr.reduce((op,inp,index)=>{
op[inp] = op[inp] || []
op[inp].push(index)
if(inp > max){
max = inp
}
return op
},{})
console.log(op[max])
Find the max value with reduce first, then find the indexes:
var arr = [0,1,4,3,4];
var max = arr.reduce((acc,curr) => curr > acc ? curr : acc);
var res = arr.reduce((acc,curr,idx) => curr === max ? [...acc, idx] : acc, []);
console.log(res);
Here's a slightly verbose solution that only iterates once. The idea is that you keep track of the highest value you've seen and compare against it.
let arr = [0,1,4,3,4];
let maxValue = arr[0];
let maxIndexes = [];
arr.forEach((val, index) => {
if(maxValue === val){
maxIndexes.push(index);
}
if(maxValue < val){
maxValue = val;
maxIndexes = [index];
}
})
console.log(maxIndexes);
Simply, Find the max value
var max_val = Math.max.apply(null, array)
Then use reduce function
var max_val_indexes = arr.reduce(function(arr, ele, i) {
if(ele === max_val)
arr.push(i);
return arr;
}, []);
To achieve expected result, use below option
Looping through using map
Capturing max index value
Filtering out max index values
var arr = [0,1,4,3,4]
const maxIndex = arr
.map((v, i, self) => v === Math.max(...self) ? i : -1)
.filter(index => index !== -1);
console.log(maxIndex)
There's no reason to find the max value and then loop again through the array. You can just keep track of the current max value as you traverse the array once:
let arr = [0,1,4,3,4]
let maxIndexes = arr.reduce((maxes, n, i, a) => {
let cur = a[maxes[0]] // current max value
if (cur == undefined || n > cur) return [i]
return (cur == n) ? maxes.concat(i) : maxes
}, [])
console.log(maxIndexes)
Here's a fairly simple version. Once you have the maximum value, iterate over the list testing each one for a match, adding it's index if it's equal:
const allMax = (xs, max = Math.max(...xs)) =>
xs.reduce((all, x, i) => x == max ? [...all, i] : all, [])
console.log(allMax([0, 1, 4, 3, 4]))
You could fix this up to run in a single pass (skipping the Math.max call) but the code would be more complex.
Update
This is that second version I mentioned:
const allMax = (xs) => xs.reduce(
(a, x, i) => x > xs[a[0]] ? [i] : x < xs[a[0]] ? [...a] : [...a, i],
[0]
)
console.log(allMax([0, 1, 4, 3, 4]))
This does everything in one pass. It will return [0] if you supply an empty list, which might be a problem, but it's hard to know what to do with it. One advantage is that it will work on other sorts of input. allMax(['a', 'b', 'd', 'c', 'd']) //=> [2, 4]. Dates should also work or anything you can compare with <.
And it's not as complex as I imagined.
you can get two array one if the duplicate maxim and another is the indexof the maxim number. please check the below code it might help you bro
let a = [1,3,6,6]
Math.max.apply( Math, a );
let index =[];
let y=0;
let maxValue = a.reduce( function (value,obj){
if(Math.max.apply( Math, a) == obj){
index.push(y);
value.push(obj);
}
++y;
return value;
},[]);
console.log(maxValue);
console.log(index);
I have an array like this:
array = [[3, 'name'],[4, 'lastname'],[2, 'name'],[4, 'lastname']]
I need to sum the values if they have equal second element:
array = [[5, 'name'],[8, 'lastname']]
I tried to sort array by alphabetic order, I know there won't be more than one duplicate, and then if item is equal to next one sum their values, else do nothing. Maybe the condition should be stringified, this is just to show what I tried...
for(var n=0; n<finish.length; n++) {
if(finish[n][1] === finish[n+1][1]) {
finish[n][0] += finish[n+1][0];
} else {
finish[n][0] = finish[n][0];
}
}
The loop returns this error: Cannot read property '1' of undefined
You can use reduce to summarise the data into an object. Use Object.values to convert the object into array
let array = [[3, 'name'],[4, 'lastname'],[2, 'name'],[4, 'lastname']];
let result = Object.values(array.reduce((c, v) => {
if (c[v[1]]) c[v[1]][0] += v[0]; //Add the first element if already exist
else c[v[1]] = v; //Assign the value if does not exist
return c;
}, {}));
console.log(result);
You can also use Map to get the desired output:
let array = [[3, 'name'],[4, 'lastname'],[2, 'name'],[4, 'lastname']];
let map = ((m, a) => (array.forEach(c => {
let [num, str] = c;
m.set(str, (m.get(str) || 0) + num);
}), m))(new Map(), array);
let result = [...map.entries()].map(([a, b]) => [b, a]);
console.log(result);
You go up to n< length, but you reference an index of n+1 in
if(finish[n][1] === finish[n+1][1])
So, in this case, once you get to n = 3, the n+1 part is referencing an element that is not defined, and thus the error.
To fix this, you need to go up to (n < length-1)
I have an array of strings:
array = ["Henry","Brian","Henry","Matilda","Henry","Brian","Matthew"]
And want to sort them into a list which orders the array by the most commonly occuring items first, but then also deletes them afterwards to create a list like so:
sortedArray = ["Henry","Brian","Matilda","Matthew"]
Is there a way of doing this in javascript?
You could use this ES6 function which runs in O(nlogn), not O(n²) as some other solutions:
var array = ["Henry","Brian","Henry","Matilda","Henry","Brian","Matthew"]
var result = [...array.reduce( (acc, s) => acc.set(s, (acc.get(s) || 0)+1), new Map )]
.sort( (a, b) => b[1] - a[1] )
.map( a => a[0] );
console.log(result);
It first creates a map, by keeping a count for each string (runs in linear time).
Then this map is transformed to an array of pairs (with spread [... ]), which is then sorted ( O(nlogn) ) by that count.
Finally, the count is dropped again from that array, using .map()
First create hash table with the array elements and the number of occurences - then sort it.
See demo below:
var array = ["Henry","Brian","Henry","Matilda","Henry","Brian","Matthew"];
var hash = array.reduce(function(p,c) {
p[c] = (p[c] || 0) + 1;
return p;
},{});
// console.log(hash);
var result = Object.keys(hash).sort(function(a,b){
return hash[b] - hash[a];
});
console.log(result);
array.sort((a, b) =>
array.filter(e => e === b).length - array.filter(e=> e === a).length
)
Then , remove duplicated items :
[... new Set(array)]
let array = ["Henry", "Brian", "Henry", "Matilda", "Henry", "Brian", "Matthew"]
array = array.sort((a, b) =>
array.filter(e => e === b).length - array.filter(e => e === a).length
)
console.log(
[...new Set(array)]
)
You could count all items and sort the keys later with the count descending.
var array = ["Henry", "Brian", "Henry", "Matilda", "Henry", "Brian", "Matthew"],
count = Object.create(null),
result;
array.forEach(function (a) {
count[a] = (count[a] || 0) + 1;
});
result = Object.keys(count).sort(function (a, b) { return count[b] - count[a]; });
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I guess the hash method should be fastest, yet here is another way which utilizes .findIndex() to run only among the unique items which might turn out to be not so bad as well. It just swaps the unique items array (p) with the previous one if it's length is bigger than the previous one.
var data = ["Henry","Brian","Henry","Matilda","Henry","Brian","Matthew","Matthew","John","Matthew"],
result = data.reduce(function(p,c){
var fi = p.findIndex(f => f[0] === c);
return fi === -1 ? (p.push([c]), p)
: (p[fi].push(c),
fi ? (p[fi].length > p[fi-1].length && ([p[fi-1],p[fi]] = [p[fi],p[fi-1]]),p)
: p);
},[])
.map(e => e[0]);
console.log(result);
Given an array with characters such as ["A","P","P","L","E","S","A","R","E"], I'm trying to create a function that will loop over the elements in the array, and create an array for each character, which will then be put into a master array. The master array will end up looking like[["A"],["P","P"],["L"],["E"],["S"],["A"],["R"],["E"] at the end, using a comparator function to check values (a,b) => a == b. Essentially, it needs to check each successive letter, and if they are the same, group into their own array within the master. The two A's should not be grouped together, since they aren't successive.
var arr = ["A","P","P","L","E"];
var master = [];
arr.sort(function(a,b){
for(var i = 0; i <= arr.length; i++){
compare each element to its successor. if successor is the same, create array of like elements ["A"],["C","C"],["B"] within final array
if(i + 1 == i){
master.push(i);
}
}
});
Just loop through the array and compare the last value to the current one.
DO NOT SORT -- that will change the order of your input array!
const coolFn = (arr) => {
return arr.reduce((rez, value, index) => {
if (index !== 0 && rez[rez.length - 1][0] === value) {
rez[rez.length - 1].push(value);
} else {
rez.push([value]);
}
return rez;
}, []);
}
const rez = coolFn('APPLES ARE NOT A BANANA PUDDING CUP'.split(''));
console.log(rez);
Can be accomplished pretty easily with Set to get unique items, reduce to turn transform and filter to find matching elements:
const arr = ["A","P","P","L","E"]
// get unique keys by expanding to a Set
const letters = [...new Set(arr)].reduce((p, c) => {
// add all matching elements from original array to aggregate
p.push(arr.filter(i => i === c))
return p;
}, []);
console.log(letters);
edit: sorry, I missed the requirement (hidden in a comment in your code) that you only add by comparing each element to its successor. My solution creates an array of each letter with its number of occurrences
You might do as follows;
var arr = ["A","P","P","L","E"],
result = arr.reduce((p,c) => {var fi = p.findIndex(a => a[0] === c);
fi === -1 ? p.push([c]) : p[fi].push(c);
return p;
},[]);
console.log(result);
As per the grouping only the sequential duplicates the following should do;
var arr = ["A","P","P","L","E","S","A","R","E"],
stickTheSame = a => a.reduce((p,c) => (p[p.length-1][0] === void 0 ||
p[p.length-1][0] === c ? p[p.length-1].push(c)
: p.push([c]),
p),[[]]);
console.log(JSON.stringify(stickTheSame(arr)));