ReactJS / ES6: Searching Japanese text using includes? - javascript

So, I'm writing a client-side search and I need to look through strings of Japanese characters. I'm wondering how to do this properly?... i.e. Do I change the format of the text into utf-8 something and then search the utf-8?
Example:
All my data has japaneseData.title : "フェリーチェ三田"
When I type in my search.value as : "フェ" using japaneseData.title.includes(search.value) I don't get a match...
How do I do this correctly?
Okay, after further inspection, the comments were correct and includes was finding the substring. This is all happening inside of a filter() and I'm trying to return the objects that match...
After changing my code to:
let filteredArrayofObjects = Lists.houseLists.filter(house => house.building_name.includes(query.search));
I was getting back some but not all. Problem cases:
"アーバイルスパシエ芝浦BAY-SIDE".includes("エ芝浦"); // this evaluates to true, but does not get included in my filtered array...
Okay, further digging, it seems the issue is I need to wait for the filter process before returning the results... haven't yet found a solution to that just yet.
async filter(arr, callback) {
return (await Promise.all(
arr.map(async item => {
return (await callback(item)) ? item : undefined;
})
)).filter(i => i !== undefined);
}
handleFilterLists = async (query = {}) => {
const { Lists } = this.props;
let searchResults = await this.filter(Lists.houseLists, async house => {
return house.building_name.includes(query.search);
// the final evaluation to look similar to this:
// var newArray = homes.filter(function (el) {
// return el.price <= 1000 &&
// el.sqft >= 500 &&
// el.num_of_beds >=2 &&
// el.num_of_baths >= 2.5;
// });
});
this.setState({ searchResults });
}
Okay, so, I'm trying to set state.searchResults after the filter method has checked for matching objects in the array Lists.houseLists...

includes returns true or false if the substring is detected or not. If you want the index of where the first detected substring begins, use indexOf.
I used your sample source and search text with includes and it returns true.
Edit:
I used your updated data and this still works. https://codepen.io/anon/pen/RMWpwe
const sourceText = 'アーバイルスパシエ芝浦BAY-SIDE';
const searchText = 'エ芝浦';
const lists = [
'スパシエ',
'芝浦BAY-SIDE',
'エ芝浦',
'パシエ芝浦BAY'
];
console.log(lists.filter(item => item.includes(searchText)));
// ["エ芝浦", "パシエ芝浦BAY"]

Related

Filtering an array based on presence of string value

I know filter questions are covered extensivly on SO - but I'm struggling to implement my idea:
I want to filter through my panels & return an array filteredPanelTabItems for any that include the layouthint: "tab-view-item" and then the remainder of the array (without "tab-view-item") to another const so I can use it elsewhere, can anyone guide where I'm going wrong?
The screenshot above shows what's happening in the console when I log:
panel.panelLinks.links
const hasTabItemViewHint() => {
//check for string
}
const filteredPanelTabItems = panel.panelLinks.links.filter<Node>(
(panelLink) => panelLink.(call hasTabItemViewHint function?)
);
Consider something like this.
var filteredPanelTabItems = $.map(panel.panelLinks.links, function(l, i) {
if (l.LinkModal.layouthint._collections.indexOf("tab-view-item") >= 0) {
return l;
}
});
See more: https://api.jquery.com/jquery.map/

no exact match with indexOf

I seem to be having a problem with indexOf to get an exact match.
I have an API that searches for items in MongooseDB where the search query matches. This works only to some extend.
Here is the used code:
exports.searchItems = (req, res) => {
console.log(req.query.searchQuery);
if (!req.query || !req.query.searchQuery) {
return res.status(400).send({
message:"'searchQuery' param should be passed with valid query!"
});
}
Item.find().then(itemsList => {
if(!itemsList) {
return res.status(404).send({
message: "No Items found for search query: " + req.query.searchQuery
});
}
var items = [];
const queryVal = req.query.searchQuery;
itemsList.forEach(function(item){
if(item) {
if(JSON.stringify(item).indexOf(queryVal) > -1) {
items.push(item);
}
}
});
res.status(200).send({items});
}).catch(err => {
res.status(500).send({
message: err.message || "Some error occured while fetching all items!"
});
});
};
Now let's say the search query is "LO_Buehne2" the result will be:
{"items":[{"_id":"5f9fcf321337250c6815ac47","ort":"LO_Buehne2","bezeichnung":"ABB Beleuchtungsstärkemessgerät","seriennummer":"H42805104","pruefdatum":"01.01.2021","ausgeliehen":false,"ausleih_datum":"","ausleih_name":"","ausleih_nummer":"","rueckgabe_datum":"","einsatzort":"","notiz":"","url":"http://192.168.1.48/fileserver/uploads/asfgasfasf.jpg","createdAt":"2020-11-02T09:19:46.287Z","updatedAt":"2021-03-19T10:41:45.591Z","__v":0}]}
This is correct since there is only one item with "ort":"LO_Buehne2"
But if I search for LO_Buehne the result will be this:
{"items":[{"_id":"5f8fe281ee35da3068b0ac49","ort":"LO_Buehne","bezeichnung":"Panasonic Akku- u. Schlagschrauber","seriennummer":"9090442 / 9080163","pruefdatum":"01.01.2021","ausgeliehen":false,"ausleih_datum":"","ausleih_name":"","ausleih_nummer":"","rueckgabe_datum":"","einsatzort":"","url":"http://192.168.0.65/fileserver/3.jpg","createdAt":"2020-10-21T07:25:53.855Z","updatedAt":"2021-03-19T10:37:17.774Z","__v":0,"notiz":""}
...
...
...
{"_id":"5f9fcf321337250c6815ac47","ort":"LO_Buehne2","bezeichnung":"ABB Beleuchtungsstärkemessgerät","seriennummer":"H42805104","pruefdatum":"01.01.2021","ausgeliehen":false,"ausleih_datum":"","ausleih_name":"","ausleih_nummer":"","rueckgabe_datum":"","einsatzort":"","notiz":"","url":"http://192.168.1.48/fileserver/uploads/asfgasfasf.jpg","createdAt":"2020-11-02T09:19:46.287Z","updatedAt":"2021-03-19T10:41:45.591Z","__v":0}
As you can see, it finds all items with "ort":"LO_Buehne" but it will also find that one item with "ort":"LO_Buehne2".
Question is...why? And how do I fix this?
If you're looking for an exact match you have two solutions.
Regex magic
Work with javascript objects and === instead of JSON strings.
1. Regex Solution
const search = 'LO_Buehne';
const reg = new RegExp(`"${search}"`);
console.log(reg.test('{opt: "LO_Buehne2"}')); // fail
console.log(reg.test('{opt: "LO_Buehne"}')); // works
This is simple regex that looks to see if the search term you're looking for is surrounded by " (double quotes). This will only work for values in double quotes.
2. Working with objects
const data = {"items":[{"_id":"5f9fcf321337250c6815ac47","ort":"LO_Buehne2","bezeichnung":"ABB Beleuchtungsstärkemessgerät","seriennummer":"H42805104","pruefdatum":"01.01.2021","ausgeliehen":false,"ausleih_datum":"","ausleih_name":"","ausleih_nummer":"","rueckgabe_datum":"","einsatzort":"","notiz":"","url":"http://192.168.1.48/fileserver/uploads/asfgasfasf.jpg","createdAt":"2020-11-02T09:19:46.287Z","updatedAt":"2021-03-19T10:41:45.591Z","__v":0},{"_id":"5f8fe281ee35da3068b0ac49","ort":"LO_Buehne","bezeichnung":"Panasonic Akku- u. Schlagschrauber","seriennummer":"9090442 / 9080163","pruefdatum":"01.01.2021","ausgeliehen":false,"ausleih_datum":"","ausleih_name":"","ausleih_nummer":"","rueckgabe_datum":"","einsatzort":"","url":"http://192.168.0.65/fileserver/3.jpg","createdAt":"2020-10-21T07:25:53.855Z","updatedAt":"2021-03-19T10:37:17.774Z","__v":0,"notiz":""}]}
const search = 'LO_Buehne';
const res = data.items.filter(item => {
return new Set(Object.values(item)).has(search);
});
console.log(res);
This solution consists in doing a strict equal to see if the value exists. In the above example I use a combination of Object#values and Set, but it's completely doable with Array#find / Array#findIndex.
i.e.:
const res = data.items.filter(item => {
return Object.values(item).findIndex(value => value === search) > -1;
});

How do I use javascript includes to filter out text that does not include specific text

I have a method that gets a list of saved photos and determines the number of photos listed. What I wish to do is return the number of photos that contain the text "Biological Hazards" in the name. Here is my code so far
getPhotoNumber(): void {
this.storage.get(this.formID+"_photos").then((val) => {
this.photoResults = JSON.parse(val);
console.log("photoResults", this.photoResults);
// photoResults returns 3 photos
// Hazardscamera_11576868238023.jpg,
// Biological Hazardscamera_11576868238023.jpg,
// Biological Hazardscamera_11576868351915.jpg
this.photoList = this.photoResults.length;
console.log("photoList", this.photoList); // returns 3
this.photoListTwo = this.photoResults.includes('Biological Hazards').length; // I wish to return 2
}).catch(err => {
this.photoList = 0;
});
}
Any help would be greatly appreciated.
Xcode log
[
One way to do this is to .filter() the array, and then calculate the length of that array.
this.photoListTwo = this.photoResults.filter(photoString => {
return photoString === 'Biological Hazards' //or whatever comparison makes sense for your data
}).length;
Quick solution for this (sorry for the lack of better formating, posting from mobile):
const array = ["Hazardscamera_11576868238023.jpg", "Biological Hazardscamera_11576868238023.jpg", "Biological Hazardscamera_11576868351915.jpg"];
const filterBioHazards = (str) => /Biological Hazards/.test(str);
console.log(array.filter(filterBioHazards).length);
// Prints 2
The method includes returns boolean to indicate whether the array contains a value or not. What you need is to filter your array and return its length after.
You need to replace the line:
this.photoListTwo = this.photoResults.includes('Biological Hazards').length;
By this:
this.photoListTwo = this.photoResults.filter(function(result) {return result.contains("Biological Hazards");}).length;

Javascript's method forEach() creates array with undefined keys

I am building a simple todo app, and I'm trying to get the assigned users for each task. But let's say that in my database, for some reason, the tasks id starts at 80, instead of starting at 1, and I have 5 tasks in total.
I wrote the following code to get the relationship between user and task, so I would expect that at the end it should return an array containing 5 keys, each key containing an array with the assigned users id to the specific task.
Problem is that I get an array with 85 keys in total, and the first 80 keys are undefined.
I've tried using .map() instead of .forEach() but I get the same result.
let assignedUsers = new Array();
this.taskLists.forEach(taskList => {
taskList.tasks.forEach(task => {
let taskId = task.id;
assignedUsers[taskId] = [];
task.users.forEach(user => {
if(taskId == user.pivot.task_id) {
assignedUsers[taskId].push(user.pivot.user_id);
}
});
});
});
return assignedUsers;
I assume the issue is at this line, but I don't understand why...
assignedUsers[taskId] = [];
I managed to filter and remove the empty keys from the array using the line below:
assignedUsers = assignedUsers.filter(e => e);
Still, I want to understand why this is happening and if there's any way I could avoid it from happening.
Looking forward to your comments!
If your taskId is not a Number or autoconvertable to a Number, you have to use a Object. assignedUsers = {};
This should work as you want it to. It also uses more of JS features for the sake of readability.
return this.taskLists.reduce((acc, taskList) => {
taskList.tasks.forEach(task => {
const taskId = task.id;
acc[taskId] = task.users.filter(user => taskId == user.pivot.task_id);
});
return acc;
}, []);
But you would probably want to use an object as the array would have "holes" between 0 and all unused indexes.
Your keys are task.id, so if there are undefined keys they must be from an undefined task id. Just skip if task id is falsey. If you expect the task id to possibly be 0, you can make a more specific check for typeof taskId === undefined
this.taskLists.forEach(taskList => {
taskList.tasks.forEach(task => {
let taskId = task.id;
// Skip this task if it doesn't have a defined id
if(!taskId) return;
assignedUsers[taskId] = [];
task.users.forEach(user => {
if(taskId == user.pivot.task_id) {
assignedUsers[taskId].push(user.pivot.user_id);
}
});
});
});

React.js – filter multiple indexOf

Im just looking for a bit of advice regarding React.js filtering. I am currently filtering ‘peopleList’ by ‘employeeName’ and this is working fine, im getting back exactly what I expect.
But I wanted to also filter by the ‘employeeID’ at the same time i.e. check if ‘employeeName’ or ‘employeeID’ contain an indexOf.. Is this possible or would I need to set up two filters for 'employeeName’ and 'employeeID’?
let people= this.state.peopleList.filter(
(person) => {
return person.record.employeeName.toLowerCase().indexOf(this.state.search.toLowerCase()) !== -1;
// return person.record.employeeID.toLowerCase().indexOf(this.state.search.toLowerCase()) !== -1;
}
);
If your condition is either one OR the other, you can use the || operator
const { search, peopleList } = this.state
const searchStr = search.toLowerCase()
const people = peopleList.filter((person) =>
person.record.employeeName.toLowerCase().indexOf(searchStr) !== -1 ||
person.record.employeeId.indexOf(searchStr) !== -1
)

Categories