Grouping arrays based on duration string - javascript

I need to group elements in different containers based on overlapping periods. Let's say we have the following array:
const periods = ['1-4', '1-7', '1-4', '1-8', '1-8', '5-8', '9-12', '9-12'];
I need it to turn into:
[['1-4', '5-8', '9-12'], ['1-7', '9-12'], ['1-4'], ['1-8'], ['1-8']]
Basically, elements get pushed into a "row". If the element's period overlaps with another inside the current row, it would create another one.
In this example '1-4', '5-8' and '9-12' are grouped because their periods do not overlap.
I'm doing this with DOM elements, I used arrays in an attempt to simplify things. Any ideas?

Mayby this code can help you to solve your case.
const periods = ["1-4", "1-7", "1-4", "1-8", "1-8", "5-8", "9-12", "9-12"];
const groupPeriods = (periods) => {
const groups = {};
const listOfPeriodsGlobal = [...periods];
for (let i = 0; i < periods.length; i++) {
const joinPeriods = [];
const listOfPeriods = [...listOfPeriodsGlobal];
for (let j = 0; j < listOfPeriods.length; j++) {
if (isInRange(listOfPeriods[j], joinPeriods)) {
joinPeriods.push(listOfPeriods[j]);
listOfPeriodsGlobal.splice(j, 1);
}
}
groups[i] = joinPeriods;
}
return groups;
};
const isInRange = (period, joinPeriods) => {
let respose = true;
for (let i = 0; i < joinPeriods.length; i++) {
const range = joinPeriods[i];
const rangesplited = range.split("-");
const periodsplited = period.split("-");
if (
(parseInt(periodsplited[0]) >= parseInt(rangesplited[0]) &&
parseInt(periodsplited[0]) <= parseInt(rangesplited[1])) ||
(parseInt(periodsplited[1]) >= parseInt(rangesplited[0]) &&
parseInt(periodsplited[1]) <= parseInt(rangesplited[1]))
) {
respose = false;
} else {
response = true;
}
}
return respose;
};
console.log(groupPeriods(periods));

You could find the group with checking the last value against the start value.
const
periods = ['1-4', '1-7', '1-4', '1-8', '1-8', '5-8', '9-12', '9-12'],
groups = periods.reduce((r, p) => {
const
start = +p.split('-', 1),
t = r.find(a => +a.at(-1).split('-')[1] < start);
if (t) t.push(p);
else r.push([p]);
return r;
}, []);
console.log(groups);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

How to use map on two arrays of the same length and compare them

So what i'm wondering is how do i give the first character of the splitted string an id of 0, and push a corresponding id into Uids[]. I'm trying to make a speed typing game, and i need to give the first character an id of 0, and so on, so that i can check user input against my string, one by one.
let sitatRandom = sitat_array[Math.floor(Math.random() * sitat_array.length)];
// Zip higher order function
const zip = (a, b) => a.map((k, i) => [k, b[i]]);
var sitat_splitted = sitatRandom.split();
var uids = [];
for (let i = 0; i < sitat_splitted.length; i++) {
const id = 'id' + Math.random().toString(16).slice(2);
uids.push(id);
}
const uid_splitted = zip(sitat_splitted, uids);
function fyllSitat() {
const sitat_div = document.getElementById('sitat');
for (let i = 0; i < uid_splitted.length; i++) {
var new_span = document.createElement('span');
new_span.setAttribute('id', uid_splitted[i][1]);
new_span.innerText = `${uid_splitted[i][0]}`;
sitat_div.appendChild(new_span);
}
}

I'm solving Leetcode problem: 14 using Javascript

I sorted the elements and comparing the first and last string to check the common prefixes. It works for most of the cases, but not for the input ["dog","racecar","car"]. The expected output is "", but what I'm getting is "c" (The "r" in "car" and "r" in "racecar"). I can tell the code to remove the last char, but this will break the other cases such as ["car", "car", "car"]. Not sure what am I missing. Any insights would help me improve.
Thanks
var longestCommonPrefix = function(strs) {
let count=0
const sortedString = strs.sort()
const firstString = sortedString[0]
const lastString = sortedString[sortedString.length-1]
for(let i=0; i< firstString.length; i++) {
if(firstString.charAt(i) === lastString.charAt(i)) {
count++
}
}
console.log(firstString.substring(0, count))
};
longestCommonPrefix(
["dog","racecar","car"])
You need to break out of the loop as soon as a match is not found. Otherwise, for example, ra and ca match on the second index, the a - which is undesirable.
var longestCommonPrefix = function(strs) {
let count = 0
const sortedString = strs.sort()
const firstString = sortedString[0]
const lastString = sortedString[sortedString.length - 1]
for (let i = 0; i < firstString.length; i++) {
if (firstString.charAt(i) === lastString.charAt(i)) {
count++
} else {
break;
}
}
console.log(firstString.substring(0, count))
};
longestCommonPrefix(
["dog", "racecar", "car"])
or, refactored a bit
const longestCommonPrefix = (strs) => {
strs.sort();
const firstString = strs[0];
const lastString = strs[strs.length - 1];
let prefixSoFar = '';
for (let i = 0; i < firstString.length; i++) {
if (firstString[i] === lastString[i]) {
prefixSoFar += firstString[i];
} else {
return prefixSoFar;
}
}
return prefixSoFar;
};
console.log(longestCommonPrefix(["dog", "racecar", "car"]));

Javascript split strings in array on specific index

I have this array of strings.
const numbersArray = ['1000','10000','100000']
My goal is to split each one of them on specific index for example: output of 1000 should be 1,000 and etc...
Here is what i have right now:
const splitArrayHandler = (arr) =>{
for (let i = 0; i < arr.length; i++) {
let indexOfSymbol = Math.round(arr[i].length / 3)
return splitAtIndex(arr[i],indexOfSymbol)
}
}
const splitAtIndex = (value,index) => {
return value.substring(0,index) + ',' + value.substring(index)
}
splitArrayHandler(numbersArray)
The first function splitArrayHandler loops through my array,finds specific index of the symbol in the string and then function splitAtIndex does the rest of the hard work.
The problem is only first element of the string is passing to the splitAtIndexfunction and I dont understand why. any suggestions please?
const numbersArray = ['1000','10000','100000']
const splitArrayHandler = (arr) =>{
for (let i = 0; i < arr.length; i++) {
let indexOfSymbol = Math.round(arr[i].length / 3)
return splitAtIndex(arr[i],indexOfSymbol)
}
}
const splitAtIndex = (value,index) => {
return value.substring(0,index) + ',' + value.substring(index)
}
splitArrayHandler(numbersArray)
Use Intl.NumberFormat for the job. No need for string parsing / manipulating:
const numbersArray = ['1000', '10000', '100000', '654654686156', '1000.66', '10e14', '0xFFFF'];
const format = new Intl.NumberFormat('en-US').format;
const formattedNumbers = numbersArray.map(Number).map(format);
console.log(formattedNumbers);
You are breaking the loop by returning the splitAtIndex function. Create another array and push the results to it.
const splitArrayHandler = (arr) =>{
let arr2 = []
for (let i = 0; i < arr.length; i++) {
let indexOfSymbol = Math.round(arr[i].length / 3)
arr2.push(splitAtIndex(arr[i],indexOfSymbol))
}
return arr2
}
You might use regular expression and map function (though there is no real difference between map and hard coded loop)
const numbersArray = ['1000','10000','100000']
function addComa(x) {
return x.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
}
const resolved = numbersArray.map(addComma)
console.log(resolved) // ['1,000','10,000','100,000']

How to extract the month values from the res.body.results array of objects using JS Array map()

Also trying to get that custom code that extracts the months from the string with regex in my code snippet. I believe I am close but not quite. Console log is returning "undefined" values for the key/value pairs and 0 for the months when it should return 60. Any thoughts on how to restructure this would be very much appreciated! I am trying to get the highest number of months/years from an array and set it to a property in HubSpot. Thank you kindly for any advice on how to properly configure to get correct values.
hubspotClient.crm.lineItems.batchApi.read({
inputs,
properties: ['hs_recurring_billing_period', 'recurringbillingfrequency',]
})
.then(res => {
const inputs = res.body.results.map(result => {
result.properties.recurringbillingfrequency =
result.properties.recurringbillingfrequency;
result.properties.months = Number(result.properties.months);
return { term: hs_recurring_billing_period, frequency: recurringbillingfrequency };
})
console.log(inputs);
let term = 0;
const largestNum = (years) => {
//let term = 0;
for (let i=0; i <res.body.results.length; i++){
let { recurringbillingfrequency, hs_recurring_billing_period } =
res.body.results[i].properties;
console.log(recurringbillingfrequency, hs_recurring_billing_period)
if(recurringbillingfrequency = "Annually")
{
let months = Number(hs_recurring_billing_period.replace(/\D/g, ''));
let years = months / 12;
// let term = 0;
if (years[i] > term) {
term = years[i];
}
}
}
return term;
}
console.log(largestNum(term));
return;
The map function looks strange to me:
const inputs = res.body.results.map(result => {
result.properties.recurringbillingfrequency = result.properties.recurringbillingfrequency;
result.properties.months = Number(result.properties.months);
return { term: hs_recurring_billing_period, frequency: recurringbillingfrequency };
})
within the scope of the mapping function, recurringbillingfrequency and hs_recurring_billing_period in the return object are not defined. Would it work by replacing the return value with as so?
return {
hs_recurring_billing_period: result.properties.hs_recurring_billing_period,
recurringbillingfrequency: result.properties.recurringbillingfrequency
};
Also, I am not quite sure how this line is necessary:
result.properties.recurringbillingfrequency = result.properties.recurringbillingfrequency;
So either this loop will work and extract the months and set to years or you can use Lodash with one line of code.
let term = 0;
for (let i=0; i <inputs.length; i++){
let { recurringbillingfrequency, hs_recurring_billing_period } =
inputs[i];
console.log(recurringbillingfrequency, hs_recurring_billing_period)
if(recurringbillingfrequency.toLowerCase() === 'annually')
{
let months = hs_recurring_billing_period;
let years = months / 12.0;
/*
let highest = 0;
function getHighestTerm(values) {
for (let j=0; j < values.length; j++)
if (j === 0) {
highest = values;
} else if (highest > values[j]) {
highest = values[j];
}
return highest;
}
*/
term = _.max(_.map(inputs, 'hs_recurring_billing_period')) / 12.0;

Array/Object Sorting

So there's a JSON Object, it has a list of arrays with objects in it, like AssortmentID and AssortmentParentID with a Name, AssortimentID's with an AssortmentParentID of 000-000-000 are folders, the AssortmentID's with the AssortmentParentID of another AssortmentID are the children of that folder.
How do I output the folders first, and then the children in each folder(parent).
Example:
The HTTP Request:
const url = "\url";
async function getAssortList() {
const response = await fetch(url);
const data = response.json();
const { Assortments } = data;
for (let i = 0; i < Assortments.length; i++) {
const assortItem = Assortments[i];
...(where I'm stuck)...
/////////////////////////////////////
The JSON Response:
Assortments: [
{
"AssortmentID": 123-123-123-123,
"AssortmentParentID": 000-000-000
"Name": "I am a parent"
},
{
"AssortmentID": 111-111-111-111,
"AssortmentParentID": 123-123-123-123,
"Name": "I am a kid"
}
Maybe this will help you.
Assortments.reduce((acc, curr) => {
let parent = curr["AssortmentParentID"];
if(acc[parent]){
acc[parent].push(curr)
}
else{
acc[parent] = [curr]
}
return acc;
}, {})
try below code in javascript
Assortments.sort(
function (a, b) {
var x = a.AssortmentParentID.toLowerCase();
var y = b.AssortmentParentID.toLowerCase();
if (x < y) {return -1;}
if (x > y) {return 1;}
return 0;
})
by this you will have sorted array on AssortmentParentID
Kind of, solved it myself. Still have things to do.
const parents = []; // created a new array that I'll push objects into later.
for (let i = 0; i < Assortments.length; i++) {
if (Assortments[i].AssortimentParentID == "000-000-000") {
parents.push(Assortments[i]);
}
}
for (let i = 0; i < parents.length; i++) {
parents.sort((a, b) => a.Name.localeCompare(b.Name)); // sort them alphabetically
}
If someone can show me how to do the same thing, using filter/find/etc., it would be great. Thank you!
UPDATE:
Managed to sort the parents, output them in DOM, here's the code:
for (let x in parents) {
parents[x].isFolder === false ? parents.push( parents.splice(x,1)[0] ) : 0;
}
let assortItem = parents[i].Name;
let subnavList = document.createElement("li");
let subnavLink = document.createElement("a");
subnavList.classList.add("subnav-list");
subnavList.appendChild(subnavLink);
subnavLink.classList.add("subnav-link");
subnavLink.innerHTML += assortItem;
item.appendChild(subnavList);

Categories

Resources