Render text depending on matching API Results - Axios/JS - javascript

I have this working, but it does consume quite a lot of space.
I'm wondering if there is way to refactor it more, matching API results with a smaller refactored condition, perhaps?
axios.js
import axios from 'axios';
export const Models = () => {
return axios.get('data/cars.json')
.then(response => {
return response.data
})
}
file.js
import { Models } from './axios';
let carModels = Models();
carModels.then((result) => {
var i, j, match;
match = false;
for (i = 0; i < result.length; i++) {
for (j = 0; j < result[i].countries.length; j++) {
if (result[i].countries[j].price == price &&
result[i].color == color &&
result[i].brand == brand &&
result[i].model == model &&
result[i].speed == speed)
{
match = true;
return document.querySelector('#brandTitle').textContent = result[i].brand;
}
}
}
if (match == false) {
console.log('No match found.');
}
})

you can use some() that will make sure to terminate the loop as conditions met
carModels.then(result => {
var i, j, match;
match = false;
for (i = 0; i < result.length; i++) {
match = result[i].countries.some(country => {
if (
country.price == price &&
result[i].color == color &&
result[i].brand == brand &&
result[i].model == model &&
result[i].speed == speed
) {
document.querySelector('#brandTitle').textContent = result[i].brand;
return;
}
});
}
if (match == false) {
console.log('No match found.');
}
});
to make more efficient you can use some on parent loop also
carModels.then(result => {
var match;
match = false;
result.some(res => {
match = result[i].countries.some(country => {
if (
country.price == price &&
res.color == color &&
res.brand == brand &&
res.model == model &&
res.speed == speed
) {
document.querySelector('#brandTitle').textContent = res.brand;
return;
}
});
if (match) {
return;
}
});
if (match == false) {
console.log('No match found.');
}
});

Related

find the overlap between two strings

I have a string and need to check with and get whether the following strings overlap with the start and end of my target string:
target string: "click on the Run"
search strings: "the Run button to", "code and click on"
Apparently:
"the Run button to" is overlapped at the end of target "click on the Run"
"code and click on" is overlapped at the start of target "click on the Run"
Both, "the Run" and "click on" will be the desired results.
I have come up with a function to check and get the overlapped results for the cases at the start and at the end separately.
Question:
But my code could not be able to get the expected results only if I know how the search string overlapped with the target string in the very first place. And how can I combine the searched results in one go as well?
function findOverlapAtEnd(a, b) {
if (b.length === 2) {
return "";
}
if (a.indexOf(b) >= 0) {
return b;
}
if (a.endsWith(b)) {
return b;
}
return findOverlapAtEnd(a, b.substring(0, b.length - 1));
}
function findOverlapAtStart(a, b) {
if (b.length === 2) {
return "";
}
if (a.indexOf(b) >= 0) {
return b;
}
if (a.startsWith(b)) {
return b;
}
return findOverlapAtStart(a, b.substring(1));
}
console.log(findOverlapAtEnd("click on the Run", "the Run button to"))
console.log(findOverlapAtStart("click on the Run", "code and click on"))
edited:
case in the middle is also considered, e.g.:
target string: "click on the Run"
search strings: "on the"
Return value: "on the"
You may try this
function findOverlapAtEnd(a, b, min) {
if (b.length <= min) {
return '';
}
if (a.indexOf(b) >= 0) {
return b;
}
if (a.endsWith(b)) {
return b;
}
return findOverlapAtEnd(a, b.substring(0, b.length - 1), min);
}
function findOverlapAtStart(a, b, min) {
if (b.length <= min) {
return '';
}
if (a.indexOf(b) >= 0) {
return b;
}
if (a.startsWith(b)) {
return b;
}
return findOverlapAtStart(a, b.substring(1), min);
}
const GetOverlappingSection = (target, search, min) => {
if (target.length < search.length) {
const tmp = target;
target = search;
search = tmp;
}
let overlap1 = findOverlapAtStart(target, search, min);
if (overlap1.length === 0) {
overlap1 = findOverlapAtEnd(target, search, min);
}
return overlap1;
};
const removeEmptyKeyword = overlap => {
let tmpFinaloverlap = [];
overlap.forEach((key, idx) => {
if (!(key.trim().length === 0)) {
tmpFinaloverlap = [...tmpFinaloverlap, key];
}
});
return tmpFinaloverlap;
};
// let overlap = ['click on','the Run']
const GetOverlappingOfKeyowrd1And2 = (keywordSet1, keywordSet2,min) => {
let resultSetoverlap = [];
let tmpresultSetoverlap = [];
keywordSet1.forEach(key =>
keywordSet2.forEach(k2 => {
tmpresultSetoverlap = [
...tmpresultSetoverlap,
GetOverlappingSection(key, k2, min),
];
})
);
// get the resultSetoverlap
tmpresultSetoverlap.forEach(element => {
if (element.length > 0) {
resultSetoverlap = [...resultSetoverlap, element];
}
});
return resultSetoverlap;
};
const min = 2;
//To handle overlapping issue in overlapping set, that casuing
overlap.forEach((key, idx) => {
if (idx < overlap.length - 1) {
for (let i = idx + 1; i < overlap.length; i++) {
console.log(`key: ${key}`);
console.log(`search: ${overlap[i]}`);
let overlapSection = GetOverlappingSection(key, overlap[i], min);
if (overlapSection.length > 0) {
console.log(`overlapSection: ${overlapSection}`);
overlap[idx] = overlap[idx].replace(overlapSection, '');
}
}
}
});
overlap = removeEmptyKeyword(overlap);
console.log(overlap);
overlap.forEach(key => {
keywordSet2 = keywordSet2.map((k1, idx) => {
console.log(`checking overlap keyword:'${key}' in '${k1}'`);
return k1.replace(key, '');
});
});
overlap.forEach(key => {
keywordSet1 = keywordSet1.map((k1, idx) => {
console.log(`checking overlap keyword:'${key}' in '${k1}'`);
return k1.replace(key, '');
});
});
keywordSet2 = removeEmptyKeyword(keywordSet2);
keywordSet1 = removeEmptyKeyword(keywordSet1);
overlap.forEach(key => {
text = text.replace(key, `$#k1k2$&$`);
});
keywordSet1.forEach(key => {
text = text.replace(key, `$#k1$&$`);
});
keywordSet2.forEach(key => {
text = text.replace(key, `$#k2$&$`);
});
console.log(`ResultSetoverlap after processing:${text}`);
Because I need to decompress and I find these logic puzzles fun, here's my solution to the problem...
https://highdex.net/begin_end_overlap.htm
You can view source of the page to see JavaScript code I used. But just in case I ever take that page down, here's the important function...
function GetOverlappingSection(str1, str2, minOverlapLen = 4) {
var work1 = str1;
var work2 = str2;
var w1Len = work1.length;
var w2Len = work2.length;
var resultStr = "";
var foundResult = false;
var workIndex;
if (minOverlapLen < 1) { minOverlapLen = 1; }
else if (minOverlapLen > (w1Len > w2Len ? w2Len : w1Len)) { minOverlapLen = (w1Len > w2Len ? w2Len : w1Len); }
//debugger;
//we have four loops to go through. We trim each string down from each end and see if it matches either end of the other string.
for (var i1f = 0; i1f < w1Len; i1f++) {
workIndex = work2.indexOf(work1);
if (workIndex == 0 || (workIndex != -1 && workIndex == w2Len - work1.length)) {
//we found a match!
foundResult = true;
resultStr = work1;
break;
}
work1 = work1.substr(1);
if (work1.length < minOverlapLen) { break; }
}
if (!foundResult) {
//debugger;
//reset the work vars...
work1 = str1;
for (var i1b = 0; i1b < w1Len; i1b++) {
workIndex = work2.indexOf(work1);
if (workIndex == 0 || (workIndex != -1 && workIndex == w2Len - work1.length)) {
//we found a match!
foundResult = true;
resultStr = work1;
break;
}
work1 = work1.substr(0, work1.length - 1);
if (work1.length < minOverlapLen) { break; }
}
}
if (!foundResult) {
//debugger;
//reset the work vars...
work1 = str1;
for (var i2f = 0; i2f < w2Len; i2f++) {
workIndex = work1.indexOf(work2);
if (workIndex == 0 || (workIndex != -1 && workIndex == w1Len - work2.length)) {
//we found a match!
foundResult = true;
resultStr = work2;
break;
}
work2 = work2.substr(1);
if (work2.length < minOverlapLen) { break; }
}
}
if (!foundResult) {
//debugger;
//reset the work vars...
work2 = str2;
for (var i2b = 0; i2b < w2Len; i2b++) {
workIndex = work1.indexOf(work2);
if (workIndex == 0 || (workIndex != -1 && workIndex == w1Len - work2.length)) {
//we found a match!
foundResult = true;
resultStr = work2;
break;
}
work2 = work2.substr(0, work2.length - 1);
if (work2.length < minOverlapLen) { break; }
}
}
return resultStr;
}
Hopefully that's helpful.

How to make multiple conditions inside single filter

I am trying to make a filter based on checkboxes.
The thing is js ignoring other conditions inside filter when one is active
filterData() {
return this.airlines.filter(x => {
if (this.filters.options.length != 0 || this.filters.airlines.length != 0) {
for (let i = 0; this.filters.options.length > i; i++) {
if (this.filters.options[i] == 0) {
return x.itineraries[0][0].stops == 0;
}
if (this.filters.options[i] == 1) {
return x.itineraries[0][0].segments[0].baggage_options[0].value > 0;
}
}
} else {
return x;
}
})
}
I know that return will stop the current loop, but is there any way to do it correctly?
Update-1: (When to filter record for every case checked OR case)
Replace for loop and all conditions in a single return by && for if and || condition for data:
var chbox = this.filters.options;
return $.inArray(0, chbox) != -1 && x.itineraries[0][0].stops == 0
|| $.inArray(1, chbox) != -1 && x.itineraries[0][0].segments[0].baggage_options[0].value > 0;
Hope this helps !!
$.inArray(value, arr) method will check for each checkboxes and will work for every checked ones .
Update-2 (When to filter record for every case checked AND case)
As per comment below, you are trying to use checkbox on demand so use below code:
var chbox = this.filters.options;
boolean condition = true;
if ($.inArray(0, chbox) != -1) {
conditon = conditon && x.itineraries[0][0].stops == 0;
}
if ($.inArray(1, chbox) != -1) {
conditon = conditon && x.itineraries[0][0].segments[0].baggage_options[0].value > 0;
}
return condition;
Your filter function is returning an object, which ideally should be a boolean value. Please refactor the code as below.
filterData() {
return this.airlines.filter(x => {
let result = false;
if (this.filters.options.length != 0 || this.filters.airlines.length != 0) {
for (let i = 0; this.filters.options.length > i; i++) {
if (this.filters.options[i] == 0) {
result = x.itineraries[0][0].stops == 0;
break;
} else if (this.filters.options[i] == 1) {
result = x.itineraries[0][0].segments[0].baggage_options[0].value > 0;
break;
}
}
}
return result;
})
}

How to optimize multiple filter?

I have big search panel with filters
In the computed section I use the next code
computed: {
filteredItems() {
if (this.activeFilter && this.activeFilter != 'all') {
return this.items[this.activeFilter]
.filter(item => item.name.toLowerCase().indexOf(this.search.toLowerCase()) !== -1)
.filter(item => item.itemLevel >= this.minLvl && item.itemLevel <= this.maxLvl);
} else {
let all = [];
let i;
if (this.items) {
for (i = 0; i < this.filters.length; i++) {
Array.prototype.push.apply(all, this.items[this.filters[i].value]);
}
}
return all
.filter(item => item.name.toLowerCase().indexOf(this.search.toLowerCase()) !== -1)
.filter(item => {
if (this.minLvl !== '' && this.maxLvl !== '') {
if (item.itemLevel >= this.minLvl && item.itemLevel <= this.maxLvl) return true;
} else if (this.minLvl == '' && this.maxLvl !== '') {
if (item.itemLevel <= this.maxLvl) return true;
} else if (this.minLvl !== '' && this.maxLvl == '') {
if (item.itemLevel >= this.minLvl) return true;
} else {
return true;
}
});
}
},
}
Here is I use one filter for min and max level. And when I will add more filter my code will be too big. Multiple filters can be active l at the same time.
How can I optimize my code?

how to change the loop to become a map?

I haven't found a way to change for into a map, so my plan won't use for but want to use maps in each function of this function
variantDefault = (colorId, sizeId) => {
let selected = [];
let i = 0;
if (this.props.index === 0) {
for (i = 0; i < this.props.values.length; i++) {
if (this.props.values[i].id === colorId) {
selected = this.props.values[i];
}
}
}
if (this.props.index === 1) {
for (i = 0; i < this.props.values.length; i++) {
if (this.props.values[i].id === sizeId) {
selected = this.props.values[i];
}
}
}
console.log(selected);
return selected;
};
you can try this way
variantDefault = (colorId, sizeId) => {
let selected = [];
if (this.props.index === 0) {
this.props.values.map((data) => {
if(data.id === colorId){
selected.push(data)
}
})
}
if (this.props.index === 1) {
this.props.values.map((data) => {
if (data.id === sizeId) {
selected.push(data)
}
})
}
console.log(selected);
return selected;
};
You could take Array#find and return the found item.
variantDefault = (colorId, sizeId) => this.props.values.find(
({ id }) => id === [colorId, sizeId][this.props.index]
) || [];
The use of Array.prototype.filter seems more fitting.
variantDefault = (colorId, sizeId) => {
if (this.props.index.isBetween(0, arguments.length, 1)) return [];
var compareTo = arguments[this.props.index];
return this.props.values.filter(item => item.id === compareTo);
};
If you only want to return the last element found (which is what you are doing in your example) then add an Array.prototype.pop call to the filtered array.
You can add the isBetween function by doing:
if (typeof Number.prototype.isBetween !== "function") {
Number.prototype.isBetween = function(start, end, inclusive) {
if (typeof start !== "number" || isNaN(start)) throw Error("Start is not a number");
if (typeof end !== "number" || isNaN(end)) throw Error("End is not a number");
return inclusive ? start <= this && this <= end : start < this && this < end;
};
}

SAPUI5 Filter OData model based on fields using formatter

I have a List that contains ObjectListItems with content provided by an OData service. One of this contents is the title and the property has the value as follows:
title="{ path: 'title', formatter: 'app.schedule.util.Formatter.titleText'}"
As you can see there is a formatter in this title. The OData will bring a value like "available" or "disabled" and the formatter will transform it on the text for the specific language of the user.
I'm implementing a search capability on this List and it works fine, the problem is that it searchs only on the "available" and "disabled" values, and not in the formatted texts as it would be expected as this are not the values recognized by the user.
The filter code is:
handleSearch : function (evt) {
// create model filter
var filters = [];
var query = evt.getParameter("query");
if (query && query.length > 0) {
filters.push(new sap.ui.model.Filter("booked", sap.ui.model.FilterOperator.Contains, query));
filters.push(new sap.ui.model.Filter("weekday", sap.ui.model.FilterOperator.Contains, query));
filters.push(new sap.ui.model.Filter("title", sap.ui.model.FilterOperator.Contains, query));
filters = new sap.ui.model.Filter(filters, false);
}
// update list binding
var list = this.getView().byId("list");
var binding = list.getBinding("items");
binding.filter(filters);
},
Any idea on how to consider the formatter on the filter and not only the raw data?
Solution Considering you are doing only client side search:
Assumption: if you have grouping in the list..
handleSearch : function (evt) {
sFilterPattern = evt.getParameter("query");
sFilterPattern = sFilterPattern.toLowerCase();
var aListItems = this.getView().byId("list").getItems();
var bVisibility;
var oGroupItem = null;
var iCountInGroup = 0;
for (var i = 0; i < aListItems.length; i++) {
if (aListItems[i] instanceof sap.m.GroupHeaderListItem) {
if (oGroupItem) {
if (iCountInGroup == 0) {
oGroupItem.setVisible(false);
} else {
oGroupItem.setVisible(true);
oGroupItem.setCount(iCountInGroup);
}
}
oGroupItem = aListItems[i];
iCountInGroup = 0;
} else {
bVisibility = this.applySearchPatternToListItem(aListItems[i], sFilterPattern);
aListItems[i].setVisible(bVisibility);
if (bVisibility) {
iCountInGroup++;
}
}
}
if (oGroupItem) {
if (iCountInGroup == 0) {
oGroupItem.setVisible(false);
} else {
oGroupItem.setVisible(true);
oGroupItem.setCount(iCountInGroup);
}
}
}
applySearchPatternToListItem:function(oItem, sFilterPattern) {
if (sFilterPattern == "") {
return true;
}
//uncomment to search in oModel data
/*var oIteshellata = oItem.getBindingContext(this.sModelName).getProperty();
for (var sKey in oIteshellata) {
var sValue = oIteshellata[sKey];
// if (sValue instanceof Date) {
// //just for the filter take each number as string
// sValue = sValue.getDate() + "." +
// sValue.getMonth() + "." + sValue.getFullYear();
// }
if (typeof sValue == "string") {
if (sValue.toLowerCase().indexOf(sFilterPattern) != -1) {
return true;
}
}
}*/
// if nothing found in unformatted data, check UI elements
if ((oItem.getIntro() && oItem.getIntro().toLowerCase().indexOf(sFilterPattern) != -1)
|| (oItem.getTitle() && oItem.getTitle().toLowerCase().indexOf(sFilterPattern) != -1)
|| (oItem.getNumber() && oItem.getNumber().toLowerCase().indexOf(sFilterPattern) != -1)
|| (oItem.getNumberUnit() && oItem.getNumberUnit().toLowerCase().indexOf(sFilterPattern) != -1)
|| (oItem.getFirstStatus() && oItem.getFirstStatus().getText().toLowerCase().indexOf(sFilterPattern) != -1)
|| (oItem.getSecondStatus() && oItem.getSecondStatus().getText().toLowerCase().indexOf(sFilterPattern) != -1)) {
return true;
}
// last source is attribute array
var aAttributes = oItem.getAttributes();
for (var j = 0; j < aAttributes.length; j++) {
if (aAttributes[j].getText().toLowerCase().indexOf(sFilterPattern) != -1) {
return true;
}
}
return false;
}

Categories

Resources