How to break a loop by setting a variable? - javascript

I wrote an ajax call with two for loop.
The first cycle looks for a key whose value is "city", the second one search for a key whose value is "hamlet".
A table is displayed if any of these two values is found.
I want to set a new variable var valueFound to indicate that the values in the first cycle have already been found, in order to say "if the value in the first cycle has been found, don't search for the second value in the other for loop".
What I want is avoiding duplicates in the search results in case both of the values are found.
The code I wrote so far is the following:
success: function (data) {
for (let i = 0; i < data.features.length; i++) {
let typeCity = data.features[i].properties.geocoding.type;
if (typeCity === "city") {
let nameCity = data.features[i].properties.geocoding.name;
for (let i = 0; i < francigena.tappe.length; i++) {
let tappa = francigena.tappe[i];
let city = francigena.tappe[i].city;
let fs = francigena.tappe[i].fs;
if (city === nameCity) {
$('#tabellaEconteuti').show();
}
};
}
else if (typeCity === "hamlet") {
let nameCity = data.features[i].properties.geocoding.name;
for (let i = 0; i < francigena.tappe.length; i++) {
let tappa = francigena.tappe[i];
let city = francigena.tappe[i].city;
let fs = francigena.tappe[i].fs;
if (city === nameCity) {
$('#tabellaEconteuti').show();
}
};
};
}
},
When in the JSON array typeCity === "city" or typeCity === "hamlet" no problem, BUT it both of the values are found I get duplicates in the search results.
How can I set such a variable var valueFound to indicate that some values have already been found and breaking the loop?

success: function (data) {
cont featuresMapByCityType = dataFeaturesMapByCityType(data.features);
cont tappesMapByCityType = getTappeMapByCity(francigena.tappe);
let feature = featuresMapByCityType['city'] || featuresMapByCityType['hamlet'];
if (feature) {
let nameCity = feature.properties.geocoding.name;
cont tappe = getTappeMapByCity[nameCity];
if (tappe && tappe.city === nameCity) {
$('#tabellaEconteuti').show();
}
}
};
function dataFeaturesMapByCityType(features) {
let featuresMapByCityType = {};
features = features || [];
features.forEach(feature => {
featuresMapByCityType{feature.properties.geocoding.type} = feature;
});
return featuresMapByCityType;
}
function getTappeMapByCity(tappes) {
let tappesMapByCityType = {};
tappes = tappes || [];
tappes.forEach(tappe => {
tappesMapByCityType{tappe[i].city} = tappe;
});
return tappesMapByCityType;
}
I have organized the code and removed multiple for loops, not sure the francigena comes from. this is a rough organization of code. This might help you.

Related

Javascript, getting past values for an array of objects

I have a JavaScript array of objects which looks like
var myarr = [
{'xx':'2023-01-01,,1'},
{'ss':'2023-01-01,2,1.2'},
{'dd':'2023-01-01,4,'},
{'rr':'2023-01-01,,'},
{'ff':'2023-01-01,,'},
{'gg':'2023-01-01,,'}
];
The array is actually much bigger than that, but I have cut it down for testing purposes, some of my arrays are thousands of lines long
Each object contains a date and two comma-separated values, although I have some rows which contain 3 or 4 comma separate values
What I need to do, is if any blank comma-separated value is found on any row then get the previous comma separated value from that position to a maximum of 2 times going back, although I may need to change that to a bigger number in the future
So with my example, I would get the following output
var myarr = [
{'xx':'2023-01-01,,1.6'},
{'ss':'2023-01-01,2,1.2'},
{'dd':'2023-01-01,4,1.2'},
{'rr':'2023-01-01,4,1.2'},
{'ff':'2023-01-01,4,'},
{'gg':'2023-01-01,,'}
];
I have tried to solve this with
var myarr = [
{'xx':'2023-01-01,,1'},
{'ss':'2023-01-01,2,1.2'},
{'dd':'2023-01-01,4,'},
{'rr':'2023-01-01,,'},
{'ff':'2023-01-01,,'},
{'gg':'2023-01-01,,'}
];
var maxAttempts = 3;
for (var i = 0; i < myarr.length; i++) {
var obj = myarr[i];
var values = Object.values(obj)[0].split(",");
var date = values[0];
var value1 = values[1];
var value2 = values[2];
for (var j = 1; j <= maxAttempts; j++) {
if (!value1) {
value1 = (myarr[i-j] && Object.values(myarr[i-j])[0].split(",")[1]) || " ";
}
if (!value2) {
value2 = (myarr[i-j] && Object.values(myarr[i-j])[0].split(",")[2]) || " ";
}
if (value1 && value2) {
break;
}
}
console.log(date, value1, value2);
for (var k = 3; k < values.length; k++) {
var value = values[k];
console.log(value);
}
}
but it doesn't seem to provide the expected output.
Can someone help me with what might be wrong?
Maybe you can use something like this.
const myarr = [
{ "xx": "2023-01-01,,1" },
{ "ss": "2023-01-01,2,1.2" },
{ "dd": "2023-01-01,4," },
{ "rr": "2023-01-01,," },
{ "ff": "2023-01-01,," },
{ "gg": "2023-01-01,," }
]
function fillInBlanks(arr, maxLookBack) {
return arr.map((obj, index) => {
const key = Object.keys(obj)[0]
const value = Object.values(obj)[0]
.split(",")
.map((x, n) => {
if (x === "" && index > 0) {
for (let i = index - 1; i >= Math.max(0, index - maxLookBack); --i) {
const prev = Object.values(arr[i])[0].split(",")
if (prev[n] !== "") return prev[n]
}
} else return x
})
return Object.fromEntries([
[key, value.join(",")]
])
})
}
fillInBlanks(myarr, 2).forEach(x => console.log(x))
Here's my attempt. This will also work with any number of values per row.
const maxAttempts = 2;
myarr.reduce((modifiedAccumulation, currentObject, index) => {
const [key, csv] = Object.entries(currentObject)[0];
const splitCsv = csv.split(",");
const modifiedCsv = splitCsv
.reduce((fixedArray, currentElement, csvPos) => {
let numberToUse =
currentElement === ""
? myarr
.slice(Math.max(index - maxAttempts, 0), index)
.reduceRight((proposedNum, currentPastObj) => {
if (proposedNum !== "") return proposedNum;
let candidate =
Object.entries(currentPastObj)[0][1].split(",")[csvPos];
return candidate !== "" ? candidate : "";
}, "")
: currentElement;
return [...fixedArray, numberToUse];
}, [])
.join(",");
return [...modifiedAccumulation, { [key]: modifiedCsv }];
}, []);
This approach creates a 'window' array containing the last few entries, which is used to look up prior column values.
const myarr = [{"xx":"2023-01-01,,1"},{"ss":"2023-01-01,2,1.2"},{"dd":"2023-01-01,4,"},{"rr":"2023-01-01,,"},{"ff":"2023-01-01,,"},{"gg":"2023-01-01,,"}]
const windowSize = 2
const w = [], r =
myarr.map(e=>Object.entries(e).flatMap(([k,v])=>[k,...v.split(',')]))
.map(a=>(
w.unshift(a) > windowSize+1 && w.pop(),
a.map((_,i)=>w.find(x=>x[i])?.[i])
)).map(([k,...v])=>[k,v.join()]
).map(i=>Object.fromEntries([i]))
console.log(r)

Delete sections of URL based on the number of params that exist in a specific section

I have the following url string:
"&data=true&filterList=include|value|Location|Region|Europe|Asia;include|value|Time|Current+Month+Flag|1;include|value|Employee|Employee+Type|Employee;&decimals=5;"
I ahve tried to write a js function that will delete sections of the url string depending on the delete and key variables, for example:
let key = "Region"
let delete = "Europe"
Should result in the url string changing to the following:
"&data=true&filterList=include|value|Location|Region|Asia;include|value|Time|Current+Month+Flag|1;include|value|Employee|Employee+Type|Employee;&decimals=5;"
However if the url was :
"&data=true&filterList=include|value|Location|Region|Asia;include|value|Time|Current+Month+Flag|1;include|value|Employee|Employee+Type|Employee;&decimals=5;"
And the key and delete variables were:
let key = "Region"
let delete = "Asia"
The url would be changed to:
"&data=true&filterList=include|value|Time|Current+Month+Flag|1;include|value|Employee|Employee+Type|Employee;&decimals=5;"
The function should look at how many values in the url exist after the specified key, up until the next ";"
If the only value is the one specified in the delete variable it should delete the whole section containing the key and value starting from include to the next ";"
If the value is one of multiple then it should only delete the value
//The filterList sections are formatted as so:
include | value | Subject Area | Table | Filters... (can have multiple filters, each seperated by a pipe ("|")
//IMPORTANT: the first 2 values i.e.: include | value | are always the same and always followed by a subject are that can be anything. Therefore the bits I care about start after the third |
//I have the following function:
function deleteUrlSection(url, key, deleteValue) {
const sections = url.split(';');
let updatedSections = [];
for (let i = 0; i < sections.length; i++) {
let section = sections[i];
let keyIndex = section.indexOf(key);
if (keyIndex !== -1) {
let values = section.substring(keyIndex).split('|');
let updatedValues = [];
for (let j = 0; j < values.length; j++) {
if (values[j] !== deleteValue) {
updatedValues.push(values[j]);
}
}
if (updatedValues.length > 0) {
updatedSections.push(updatedValues.join('|'));
}
} else {
updatedSections.push(section);
}
}
return updatedSections.join(';');
}
This function works fine for the following example only:
URL = "&data=true&filterList=include|value|Location|Region|Europe|Asia;include|value|Time|Current+Month+Flag|1;include|value|Employee|Employee+Type|Employee;&decimals=5;"
let key = "Region"
let delete = "Europe"
Result:
'"&data=true&filterList=include|value|Location|Region|Asia;include|value|Time|Current+Month+Flag|1;include|value|Employee|Employee+Type|Employee;&decimals=5;"`
However if I try with the url set to:
'"&data=true&filterList=include|value|Location|Region|Asia;include|value|Time|Current+Month+Flag|1;include|value|Employee|Employee+Type|Employee;&decimals=5;"`
and variables set to:
let key = "Region"
let delete = "Asia"
I get:
&cdata=true&filterList=include|value|Location|Region;include|value|Time|Current+Month+Flag|1;include|value|Employee|Employee+Type|Employee;&decimals=5;
include|value|Location|Region should be deleted...
function deleteUrlSection(url, key, deleteValue) {
const sections = url.split(';');
let updatedSections = [];
for (let i = 0; i < sections.length; i++) {
let section = sections[i];
let keyIndex = section.indexOf(key);
if (keyIndex !== -1) {
let values = section.substring(keyIndex).split('|');
let updatedValues = [];
for (let j = 0; j < values.length; j++) {
if (values[j] !== deleteValue) {
updatedValues.push(values[j]);
}
}
if (updatedValues.length > 0) {
updatedSections.push(updatedValues.join('|'));
}
} else {
updatedSections.push(section);
}
}
return updatedSections.join(';');
}
//test 1
let url = "&data=true&filterList=include|value|Location|Region|Europe|Asia;include|value|Time|Current+Month+Flag|1;include|value|Employee|Employee+Type|Employee;&decimals=5;";
let key = "Region";
let deleteV = "Asia";
console.log("New Url ", "", deleteUrlSection(url, key, deleteV));
//expected output
//&data=true&filterList=include|value|Location|Region|Europe;include|value|Time|Current+Month+Flag|1;include|value|Employee|Employee+Type|Employee;&decimals=5;
//test 2
let url2 = "&data=true&filterList=include|value|Location|Region|Europe;include|value|Time|Current+Month+Flag|1;include|value|Employee|Employee+Type|Employee;&decimals=5;";
let key2 = "Region";
let deleteV2 = "Europe";
console.log("New Url2 ", "", deleteUrlSection(url2, key2, deleteV2));
//expected output
//&data=true&filterList=include|value|Time|Current+Month+Flag|1;include|value|Employee|Employee+Type|Employee;&decimals=5;
//test 3
let url3 = "&data=true&filterList=include|value|Location|Region|Europe|Asia;include|value|Time|Current+Month+Flag|1;include|value|Employee|Employee+Type|Employee;&decimals=5;";
let key3 = "Current+Month+Flag";
let deleteV3 = "1";
console.log("New Url3 ", "", deleteUrlSection(url, key3, deleteV3));
//expected output
//&data=true&filterList=include|value|Location|Region|Europe|Asia;include|value|Time|Current+Month+Flag|1;&decimals=5;

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"]));

Find Array[1D] in Array[2D] and return index

have any way can find a match index in array[2D] faster?
I know compare 1 by 1 can make this ok, but i don't wanted to.
I tried this one, but it only can return -1
// mainsheetvalues is array[1D],
[1,2,3,4,5]
// AsheetValues is array [2D]
[
[1,2,3,4,5],
[6,7,8,9,0]
]
Logger.log(mainsheetvalues.indexOf(AsheetValues))
As per this answer, we cannot compare two arrays directly. You need to generate some custom logic for the comparison. I have added a logic below. Hope this helps.
const AsheetValues = [
[1,2,3,4,5],
[6,7,8,9,0]
]
const mainsheetvalues = [1,2,3,4,5];
const isIncluded = (parentArr, childArr) => {
let isMatch = true;
for(let parentLoopIndex = 0; parentLoopIndex < parentArr.length; parentLoopIndex++) {
if (parentArr[parentLoopIndex].length != childArr.length)
isMatch = false;
for (var i = 0; i < parentArr[parentLoopIndex].length; i++) {
if (parentArr[parentLoopIndex][i] != childArr[i]) {
isMatch = false;
}
}
if (isMatch) {
parentLoopIndex = parentArr.length;
}
}
return isMatch;
}
console.log(isIncluded(AsheetValues, mainsheetvalues));

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