Search in the multi dimension array javascript - javascript

I am facing an issue with the java-script multidimensional array . I want to search a date and month in a given array if present .I mean i want to count dates except saturday and sunday and national holidays I have this array
var natDays = [
[1, 1, 'uk'],
[1, 19, 'uk'],
[2, 16, 'uk'],
[4, 23, 'uk'],
[7, 03, 'uk'],
[7, 04, 'uk'],
[9, 07, 'uk'],
[8, 12, 'uk'],
[11, 11, 'uk'],
[11, 26, 'uk'],
[12, 25, 'uk']
];
from reference of this answer Here . I have created my function like this
function check_hol(month,date)
{
var natDays = [
[1, 1, 'uk'],
[1, 19, 'uk'],
[2, 16, 'uk'],
[4, 23, 'uk'],
[7, 03, 'uk'],
[7, 04, 'uk'],
[9, 07, 'uk'],
[8, 12, 'uk'],
[11, 11, 'uk'],
[11, 26, 'uk'],
[12, 25, 'uk']
];
for( var md = 0; md <= natDays.length; md++ )
{
alert(natDays[md][0]+'='+month+' and '+natDays[md][1]+'='+date) ;
if( natDays[md][0] != month && natDays[md][1] != date )
{
return true;
}
}
return false;
}
I am using this function to calculate the working days in this function
function workingDays(){
var n=0;
for(var i=1; i<=dp.datediff; i++){
var d1 = new Date();
d1.setDate(d1.getDate()+i);
if(d1.getDay() !== 0&&d1.getDay()!==6 && check_hol(d1.getMonth()+1,d1.getDate())===true)
{
n++;
}
}
alert(n);
dp.wdiff = n;
getShipDays();
getProdDays();
getQuantity();
getShipProdDays();
}
but it returns 0 in the output of working days . if i remove && check_hol(d1.getMonth()+1,d1.getDate())===true from my second function it is working fine .
can't understand where i am wrong .

Instead of != the code should make use of == because you want to match when the value is found. If you do this it will search in entire array for the value.
And instead of <= in for should be < because your index start from 0.
for (var md = 0; md < natDays.length; md++) { // changed in md < natDays
if (natDays[md][0] == month && natDays[md][1] == date) { // if values are == that means the value is found
return true; // isHoliday
}
}
function check_hol(month, date) {
var natDays = [
[1, 1, 'uk'],
[1, 19, 'uk'],
[2, 16, 'uk'],
[4, 23, 'uk'],
[7, 03, 'uk'],
[7, 04, 'uk'],
[9, 07, 'uk'],
[8, 12, 'uk'],
[11, 11, 'uk'],
[11, 26, 'uk'],
[12, 25, 'uk']
];
for (var md = 0; md < natDays.length; md++) { // changed in md < natDays
if (natDays[md][0] == month && natDays[md][1] == date) { // if values are == that means the value is found
return true; // isHoliday
}
}
return false; // !isHoliday => isWorkingDay
}
alert("found: " + check_hol(11,11));
alert("found: " + check_hol(11,12));
You need to make some changes in working days because, if the value was found (true) means that is holiday.
if(d1.getDay() !== 0&&d1.getDay()!==6 && !check_hol(d1.getMonth()+1,d1.getDate()))

Related

Sort adjacent pairs into row in Javascript

Let's say I have an array of paired integers
let pairs = [
[6, 12],
[7, 6],
[8, 7],
[9, 8],
[12, 13],
[13, 14],
[14, 9]
];
All pairs creates chain by its nature, so you don't need to filter them.
So, the task is actually to build a chain from that, like
let output = [6, 12, 13, 14, 9, 8, 7];
It could be done by brute-forcing algorithm attached, but I am looking for more elegant solution.
let pairs = [
[6, 12],
[7, 6],
[8, 7],
[9, 8],
[12, 13],
[13, 14],
[14, 9]
];
let chain = [pairs[0][0], pairs[0][1]];
pairs.shift();
while(pairs.length !== 1){
let j = null;
for(let i = 0; i < pairs.length; i++){
if(pairs[i][0] === chain[chain.length - 1]) {
chain.push(pairs[i][1]);
j = i;
break;
}
if(pairs[i][1] === chain[chain.length - 1]){
chain.push(pairs[i][0]);
j = i;
break;
}
}
if(j !== null) { pairs.splice(j, 1); }
}
console.log(chain);
You should use a Map to iterate only once:
const pairs = [
[6, 12],
[7, 6],
[8, 7],
[9, 8],
[12, 13],
[13, 14],
[14, 9]
];
const pairsMap = new Map(pairs)
const chain = [pairs[0][0]]
for (let i = 0; i < pairs.length - 1; i++) {
const last = chain.at(-1)
const peer = pairsMap.get(last)
chain.push(peer)
}
console.log(chain)

JavaScript - transform this data structure

When I have this array with this data structure:
[[3, 16, 1]
[3, 17, 1]
[3, 18, 1]
[3, 19, 1]
[3, 20, 1]
[3, 19, 1]
[3, 21, 1]
[3, 23, 1]
[3, 16, 1]
[3, 17, 1]
[2, 24, 1]
[2, 25, 1]
[2, 26, 1]
[2, 24, 1]]
and I want to count array elements and multiply this to the last number of the array, like this:
[[3, 16, 2]
[3, 17, 2]
[3, 18, 1]
[3, 19, 2]
[3, 20, 1]
[3, 21, 1]
[3, 23, 1]
[2, 24, 2]
[2, 25, 1]
[2, 26, 1]]
I tried to do it with:
array.forEach(function(x) {
counts[x] = (counts[x] || 0)+1;
});
but this changes the data structure, is there another form to do it?
I rewrite your function and console.log the output you want.
Whenever I check a new array, I store it in checkedArr and will check against it to prevent duplicate records.
const arr = [
[3, 16, 1],
[3, 17, 1],
[3, 18, 1],
[3, 19, 1],
[3, 20, 1],
[3, 19, 1],
[3, 21, 1],
[3, 23, 1],
[3, 16, 1],
[3, 17, 1],
[2, 24, 1],
[2, 25, 1],
[2, 26, 1],
[2, 24, 1],
];
const checkedArr = [];
const output = [];
for (let i = 0; i < arr.length; i++) {
let count = 0;
if (!isArrayChecked(arr[i])) {
checkedArr.push(arr[i]);
for (let j = i; j < arr.length; j++) {
if (isArraySame(arr[i], arr[j])) {
count++;
}
}
output.push([arr[i][0], arr[i][1], count]);
}
}
function isArrayChecked(array) {
let exist = false;
for (let k = 0; k < checkedArr.length; k++) {
if (isArraySame(array, checkedArr[k])) {
exist = true;
break;
}
}
return exist;
}
function isArraySame(arr1, arr2) {
if (arr1[0] !== arr2[0] || arr1[1] !== arr2[1] || arr1[2] !== arr2[2])
return false;
return true;
}
console.log(output);
The problem with your code is in counts[x]. You can't use an array to index an object.
You can solve the issue by stringifying the array. That is, use:
counts[String(x)] = (counts[String(x)] || 0)+1;
let arr=[
[3, 16, 1],
[3, 17, 1],
[3, 18, 1],
[3,16,1],
[3, 19, 1],
[3, 20, 1],
[3, 19, 1],
[3, 21, 1],
[3, 23, 1],
[3, 16, 1],
[3, 17, 1],
[2, 24, 1],
[2, 25, 1],
[2, 26, 1],
[2, 24, 1]]
let solution = (arr) => {
let obj = {};
let result = [];
for (let i of arr) {
let keyOfObj = JSON.stringify(i);
obj[keyOfObj] ? obj[keyOfObj]++ : obj[keyOfObj] = 1;
}
for (let [key, value] of Object.entries(obj)) {
let objKeyArr = JSON.parse(key);
if (value >= 2) {
let lastElemt = objKeyArr[objKeyArr.length - 1];
objKeyArr.splice(objKeyArr.length - 1, 1, lastElemt * value);
result.push(objKeyArr);
} else {
result.push(objKeyArr);
}
}
return result;
};
solution(arr)

Write nested map function

I have an object like this:
const object = {
detectors: [1, 2],
responders: [4, 22],
activators: [5, 23, 31],
enablers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
upgraders: [14, 15, 16, 17, 18, 19, 20, 21, 22],
catalyzer: [12, 29],
chains: [27],
trappers: [13],
finishers: [16],
}
Expected output :
[
{
'detectors': 1,
'responders': 4,
'activators': 5,
'enablers': 1,
'upgraders': 23,
'catalyzer': 12,
'chains': 27,
'trappers': 13,
'finishers': 16,
},
{
'detectors': 2,
'responders': 4,
'activators': 5,
'enablers': 1,
'upgraders': 23,
'catalyzer': 12,
'chains': 27,
'trappers': 13,
'finishers': 16,
},
{
'detectors': 1,
'responders': 22,
'activators': 5,
'enablers': 1,
'upgraders': 23,
'catalyzer': 12,
'chains': 27,
'trappers': 13,
'finishers': 16,
},
{...
And I already wrote a function like this:
object.activators.map((activator, i) => {
return object.detectors.map((detector, i) => {
return object.responders.map((responder, i) => {
return {
detectors: detector,
responders: responder,
activators: activator,
};
});
});
});
I can write another function to flatten the output of the code above, but is there any other way to write the code above into a more general function (not hardcoded) that can apply to any object?
You can use a recursive function to get all permutations from the entries.
const object = {
detectors: [1, 2, 3],
responders: [4, 22],
activators: [1, 2, 3, 4]
};
const getPermutations = obj => {
const res = [];
const entries = Object.entries(obj);
const go = (curr, idx) => {
const key = entries[idx][0];
for(const val of entries[idx][1]){
const next = {...curr, [key]: val};
if(idx !== entries.length - 1) go(next, idx + 1);
else res.push(next);
}
};
go({}, 0);
return res;
}
console.log(getPermutations(object));

Find if arrays repeat and then select them [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I have multiple arrays in a main/parent array like this:
var arr = [
[1, 17],
[1, 17],
[1, 17],
[2, 12],
[5, 9],
[2, 12],
[6, 2],
[2, 12],
[2, 12]
];
I have the code to select the arrays that are repeated 3 or more times (> 3) and assign it to a variable.
The code is:
var arr = [[1, 17], [1, 17], [1, 17], [2, 12], [5, 9], [2, 12], [6, 2], [2, 12]]
arr.sort((a, b) => a[0] - b[0] || a[1] - b[1])
// define equal for array
const equal = (arr1, arr2) => arr1.every((n, j) => n === arr2[j])
let GROUP_SIZE = 3
first = 0, last = 1, res = []
while(last < arr.length){
if (equal(arr[first], arr[last])) last++
else {
if (last - first >= GROUP_SIZE) res.push(arr[first])
first = last
}
}
if (last - first >= GROUP_SIZE) res.push(arr[first])
console.log(res)
So the final result is:
console.log(repeatedArrays);
>>> [[1, 17], [2, 12]]
My problem: But the problem is, I have an array like this {from: [12, 0], to: [14, 30]}.
var arr = [
[1, 17],
[1, 17],
[1, 17],
[2, 12],
[5, 9],
[2, 12],
[6, 2],
{from: [12, 0], to: [14, 5]},
{from: [12, 0], to: [14, 5]},
{from: [4, 30], to: [8, 20]},
{from: [12, 0], to: [14, 5]},
{from: [4, 30], to: [8, 20]},
[2, 12],
[2, 12]
];
When I try to use the above code, it doesn't work. The error message is:
Uncaught TypeError: arr1.every is not a function
The final result should be:
console.log(repeatedArrays);
>>> [[1, 17], [2, 12], {from: [12, 0], to: [14, 5]}]
How can I make that code above work?
If you introduce a non array into the mix, you need to handle it differently.
Yours already work with array so I'm adding object style check for both sort and equal.
var arr = [
[1, 17],
[1, 17],
[1, 17],
[2, 12],
[5, 9],
[2, 12],
[6, 2],
{ from: [4, 30], to: [8, 21] },
{ from: [12, 0], to: [14, 5] },
{ from: [12, 0], to: [14, 5] },
{ from: [4, 30], to: [8, 20] },
{ from: [12, 0], to: [14, 5] },
{ from: [4, 30], to: [8, 20] },
[2, 12],
[2, 12]
];
arr.sort((a, b) => {
if (a instanceof Array && b instanceof Array) {
return a[0] - b[0] || a[1] - b[1]
} else if (a instanceof Array || b instanceof Array) {
return a instanceof Array ? -1 : 1
} else {
return a.from[0] - b.from[0] || a.from[1] - b.from[1] || a.to[0] - b.to[0] || a.to[1] - b.to[1]
}
});
// define equal for array
const equal = (arr1, arr2) => {
if (arr1 instanceof Array) {
return arr1.every((n, j) => n === arr2[j]);
} else {
if (arr2 instanceof Array) return false;
for (let k in arr1) {
if (!arr1[k].every((n, j) => n === arr2[k][j])) {
return false
}
}
return true;
}
};
let GROUP_SIZE = 3;
(first = 0), (last = 1), (res = []);
while (last < arr.length) {
if (equal(arr[first], arr[last])) last++;
else {
if (last - first >= GROUP_SIZE) res.push(arr[first]);
first = last;
}
}
if (last - first >= GROUP_SIZE) res.push(arr[first]);
console.log(res);
You can use the function reduce for grouping and counting the objects and then execute the function filter for getting the object with count >= 3.
var array = [ [1, 17], [1, 17], [1, 17], [2, 12], [5, 9], [2, 12], [6, 2], [2, 12], [2, 12] ];
let result = Object.values(array.reduce((a, [c, b]) => {
let key = `${c}|${b}`;
(a[key] || (a[key] = {count: 0, value: [c, b]})).count++;
return a;
}, {})).filter(o => {
if (o.count >= 3) {
delete o.count;
return true;
}
return false;
}).map(({value}) => value);
console.log(result);
.as-console-wrapper { min-height: 100%; }
Really simple - filter it all, then remove duplicates with Set and JSON methods (because it's nested arrays not objects):
var array = [
[1, 17],
[1, 17],
[1, 17],
[2, 12],
[5, 9],
[2, 12],
[6, 2],
[2, 12],
[2, 12]
];
var repeatedArrays = [...new Set(array.filter(e => array.filter(f => JSON.stringify(e.sort()) == JSON.stringify(f.sort()))).map(JSON.stringify))].map(JSON.parse);
console.log(repeatedArrays);

Can someone suggest some better way of writing this Javascript code

I am given an input array need to convert to output array (it's consecutive array in the output array.)
var input = [1, 3, 4, 5, 8, 9, 15, 20, 21, 22, 23, 24, 25, 26, 40];
var output = [[1], [3, 4, 5], [8, 9], [15], [20, 21, 22, 23, 24, 25, 26], [40]];
I am able to achieve this by:
let t = 0;
let tArr = []
const a = [];
input.map(i => {
if (i-t === 1) {
tArr.push(i);
} else {
a.push(tArr);
tArr = [];
tArr.push(i)
}
t = i;
});
a.push(tArr);
console.log("final", a)
Can someone suggest a cleaner code or if this could be optimized.
You could reduce the array by looking at the index or ar the former value and compare to the actual value.
var input = [1, 3, 4, 5, 8, 9, 15, 20, 21, 22, 23, 24, 25, 26, 40],
result = input.reduce((r, v, i, a) => {
if (!i || a[i - 1] + 1 < v) {
r.push([v]);
} else {
r[r.length - 1].push(v);
}
return r;
}, []);
console.log(result);

Categories