compare and store string value by array in Javascript / node js - javascript

I fetched data from database so its coming in string format and I want to check this string with my array data
my string values come like
fish.jpg
animal.jpg
fish.pdf
animal.pdf
mammal_bio.pdf
fish_bio.jpg
fruit_bio.pdf
I want to compare this data with my array which contain
["mammal_bio.pdf","fruit_bio.pdf","animal_bio.pdf","tree_bio.pdf"]
So i want to compare all the array values which contain _bio.pdf and store them
matchedArray=["mammal_bio.pdf","fruit_bio.pdf"
unmatchedArray=["animal_bio.pdf","tree_bio.pdf"]

Don't use filter but forEach or for loop instead because you don't need to loop through all items again to get the two arrays.
const input = `fish.jpg
animal.jpg
fish.pdf
animal.pdf
mammal_bio.pdf
animal_bio.pdf
fish_bio.jpg
tree_bio.pdf
fruit_bio.pdf`;
check = ["mammal_bio.pdf", "fruit_bio.pdf", "animal_bio.pdf", "tree_bio.pdf"];
const matched = [];
const unmatched = [];
input
.split("\n")
.forEach(item =>
check.slice(0, 2).includes(item)
? matched.push(item)
: check.slice(-2).includes(item)
? unmatched.push(item)
: null
);
console.log({ matched });
console.log({ unmatched });

First you can filter out the strings which endsWith _bio.pdf.
Then for matched result filter with fiterArr and similarly for unmatched result
let filterArr = ['mammal_bio.pdf','fruit_bio.pdf'];
let bioArr = arr.filter(a => a.endsWith('_bio.pdf'));
let matched = bioArr.filter(b => filterArr.includes(b));
let unmatched = bioArr.filter(b => !filterArr.includes(b));

Just use
Array.filter
method.
If you return true the item will be inside the new Array, false excludes the item.
const noBioList = []
const bioList = list.filter(item => {
if (item.includes('_bio.pdf') {
return true
} else {
noBioList.push(item)
return false
}
}
console.log(bioList)
console.log(noBioList)

const input = `fish.jpg
animal.jpg
fish.pdf
animal.pdf
mammal_bio.pdf
animal_bio.pdf
fish_bio.jpg
tree_bio.pdf
fruit_bio.pdf`;
const inputList = input.split(/\n\s*/g)
const check = ["mammal_bio.pdf", "fruit_bio.pdf"];
const { matched, unmatched } = inputList.reduce((result, file) => {
if(/_bio\.pdf/.match(file)) {
if(check.indexOf(file) < 0) result.unmatched.push(file);
else result.matched.push(file)
}
return result
}, {
matched: [],
unmatched: []
})

Related

Filter and include based on two or more strings in array

I have a query/string that I want to do a filter + include to check if that string is matching an item in another array. For example, I have this which works for a single string:
const filteredString = `${this.filter}`.toLowerCase();
this.filteredCampaigns = this.filteredCampaigns.concat(this.allCampaigns.
filter((item) => item.description?.toLowerCase().includes(filteredString) ||
item.type?.toLowerCase().includes(filteredString) ||
item.code?.toLowerCase().includes(filteredString)
));
Since I want to match multiple strings, I do a split() in my string to make it to an array and put the strings in separated elements:
const filteredString: string = `${this.filter}`.toLowerCase().split(' ');
Now thats an array, I make a for-of loop through my filter methods:
for (const val of filteredString) {
this.filteredCampaigns = this.filteredCampaigns?.concat(this.allCampaigns.
filter((item) => item.description?.toLowerCase().includes(val) ||
item.type?.toLowerCase().includes(val) ||
item.code?.toLowerCase().includes(val)
));
}
}
Problem with above is that it will filter out each element from the array independently from each other. So if my query/filteredString have two string elements, and one of the elements returns a match and the other does not, I will still get a result. But I want ALL of the items in the string to be 'connected' to each other in the filtering, and return all items that partially matches all of the strings in my array. How to do it?
Your filter string.
const filter = 'not that';
Space-separated filters.
const filteredStrings: string[] = `${filter}`.toLowerCase().split(' ');
Assuming your campaign data.
const allCampaigns = [{
description: 'This is ...',
type: 'TYPE1',
code: 'TD35'
},
{
description: 'That will be done...',
type: 'TYPE2',
code: 'TC33'
},
{
description: 'You shall not pass',
type: 'UUGG',
code: 'CD01'
}
];
Filtered campaigns
let filteredCampaigns: any[] = [];
Assign method:
filteredCampaigns = filteredCampaigns?.concat(allCampaigns.filter((item) => filteredStrings.filter(val => item.description?.toLowerCase().includes(val)).length ||
filteredStrings.filter(val => item.type?.toLowerCase().includes(val)).length ||
filteredStrings.filter(val => item.code?.toLowerCase().includes(val)).length
));
Demo
You could destructure item and check if the filter contains one of the value.
const
filter = this.filter.toLowerCase().split(/\s+/);
this.filteredCampaigns = this.allCampaigns.filter(({ description = '', type = '', code = '' }) =>
[description.toLowerCase(), type.toLowerCase(), code.toLowerCase()]
.some(word => filter.includes(word))
);
Rather than concatenating the matches to the array, I would push the matches of each string to it's own array firstly, then check if the amount of matches found is the same number of filteredStrings.
If all strings had matches, I reduce the filteredCampaigns array from 2D to 1D
else, I reset the filteredCampaigns to an empty array
const filteredString: string = `${this.filter}`.toLowerCase().split(' ');
this.filteredCampaigns = [];
for (const val of filteredStrings) {
this.filteredCampaigns.push(this.allCampaigns.filter(item => item.description?.toLowerCase().includes(val) || item.type?.toLowerCase().includes(val) || item.code?.toLowerCase().includes(val)))
}
if (this.filteredCampaigns.length == filteredStrings.length) this.filteredCampaigns.flat();
else this.filteredCampaigns = [];

Convert an array of string key pairs to an object

I have this data structure:
[
'ecl:hzl byr:1926 iyr:2010,pid:221225902 cid:61 hgt:186cm eyr:2021 hcl:#7d3b0c',
'hcl:#efcc98 hgt:178 pid:433543520,eyr:2020 byr:1926,ecl:blu cid:92,iyr:2010',
'iyr:2018,eyr:2026,byr:1946 ecl:brn,hcl:#b6652a hgt:158cm,pid:822320101'
]
I'm looking to convert those array values to objects instead of strings. I understand I need to do a map with a split(' '), but unsure of the logic inside of there.
Desired output:
[
{ecl: 'hzl', byr: 1926},
{hcl: '#efcc98', byr: 1926}
]
etc. with all of the fields.
I've tried:
.map(values => { let pair = values.split(':'); obj[pair[0]] = pair[1]; return obj })
But seem to get the same object repeated over and over, from the first index of the array.
If you're looking to get each element of the array as a separate object then try this:
const input = [
'ecl:hzl byr:1926 iyr:2010,pid:221225902 cid:61 hgt:186cm eyr:2021 hcl:#7d3b0c',
'hcl:#efcc98 hgt:178 pid:433543520,eyr:2020 byr:1926,ecl:blu cid:92,iyr:2010',
'iyr:2018,eyr:2026,byr:1946 ecl:brn,hcl:#b6652a hgt:158cm,pid:822320101'
]
const output = input.map((string) => { // for each string in array
const pairs = string.split(/[\ ,]/); // split by space or comma
const object = {}; // create an object
for (pair of pairs) { // for each pair in string
const parts = pair.split(":"); // split by colon
if (parts.length == 2) { // if you get 2 parts after splitting
object[parts[0]] = parts[1]; // use the first part as a key and the second as a value
}
}
return object;
});
console.log(output);
Try this
array = array.map(val => {
var obj = {}
val.split(' ').forEach(keyValPair => {
var keyVal = keyValPair.split(':')
obj[keyVal[0]] = keyVal[1];
})
return obj;
})
You can use Object.fromEntries.
const arr = [
'ecl:hzl byr:1926 iyr:2010,pid:221225902 cid:61 hgt:186cm eyr:2021 hcl:#7d3b0c',
'hcl:#efcc98 hgt:178 pid:433543520,eyr:2020 byr:1926,ecl:blu cid:92,iyr:2010',
'iyr:2018,eyr:2026,byr:1946 ecl:brn,hcl:#b6652a hgt:158cm,pid:822320101'
];
const res = arr.map(x => Object.fromEntries(x.replace(/,/g, ' ')
.split(' ').map(y => y.split(':'))));
console.log(res);

Sort array elements on JavaScript

I have an array, each subarray of which contains different positions in different order:
[
["apple(2)", "banana(5)"],
["peach(3)", "banana(1)"],
["apple(1)"]
]
I need to sort it on JavaScript (ES6) and i expect to get an array like this:
[
["apple(2)", "banana(5)", "peach(0)"],
["apple(0)", "banana(1)", "peach(3)"],
["apple(1)", "banana(0)", "peach(0)"]
]
Order of each subarray should be the same. If subarray don't have some position, i need to add it with 0 value. Can i using something like map() or sort() function or need to compare it manually?
Here is functional programming approach, using a Map and reduce:
const data = [['apple(2)', 'banana(5)'],['peach(3)', 'banana(1)'],['apple(1)'],];
// Create a Map with default values for each name, i.e. with "(0)":
let names = new Map(data.flat().map(item => [item.replace(/\d+/, ""), item.replace(/\d+/, "0")]));
let result = data.map(row =>
[...row.reduce((map, item) =>
map.set(item.replace(/\d+/, ""), item), // Overwrite default
new Map(names) // Start with clone of original Map
).values()]
);
console.log(result);
You have to loop over to get the keys used. You then have to loop over a second time to get the fill in the missing keys. There are many ways of doing it, this is one.
var data = [
["apple(2)", "banana(5)"],
["peach(3)", "banana(1)"],
["apple(1)"]
];
// match string and number
var re = /([^(]+)\((\d+)\)/;
// Loop over and find all of the keys
var grouped = data.reduce((info, subset, index) => {
subset.forEach(item => {
// find the key and count
var parts = item.match(re);
// have we seen this key?
if (!info[parts[1]]) {
// if not create an array
info[parts[1]] = Array(data.length).fill(0);
}
// set the key index with the count
info[parts[1]][index] = parts[2];
})
return info;
}, {});
// loop over the groups and fill in the set
Object.entries(grouped).forEach(([key, counts], colIndex) => {
counts
.forEach((cnt, rowIndex) => {
data[rowIndex][colIndex] = `${key}(${cnt})`;
})
});
console.log(data);
First get the unique words. Then traverse array of arrays to check if the word is present or not. If it is not present then make the word according to your condition and if present then put the original word to the tmp array. At last sort it for each iteration. By the way, I used regex replace method to get the word.
const data = [
['apple(2)', 'banana(5)'],
['peach(3)', 'banana(1)'],
['apple(1)'],
];
const words = [...new Set(data.flat().map((x) => x.replace(/[^a-z]/gi, '')))];
const ret = data.map((x) => {
const tmp = [];
const newX = x.map((y) => y.replace(/[^a-z]/gi, ''));
for (let i = 0, l = words.length; i < l; i += 1) {
if (newX.includes(words[i])) tmp.push(x.shift());
else tmp.push(`${words[i]}(0)`);
}
return tmp.sort();
});
console.log(ret);

Find an index of array item from another json array item

I am looking to find out an index and group the item belong to in a parent json group, how can I do it?
I am open to reformat the json as well if need be,
I tried JSON.stringify() but it returns the wrong index as well.
let Content = {
group1: [
[{content:"hello"},{content:"world"}],
[{content:"hello1"},{content:"world"}],
[{content:"hello2"},{content:"world"}],
[{content:"hello3"},{content:"world"}],
[{content:"hello4"},{content:"world"}],
[{content:"hello5"},{content:"world"}],
],
group2: [
[{content:"hello10"},{content:"world"}],
[{content:"hello11"},{content:"world"}],
[{content:"hello12"},{content:"world"}],
[{content:"hello13"},{content:"world"}],
[{content:"hello14"},{content:"world"}],
[{content:"hello15"},{content:"world"}],
],
};
// let currentItem = {type:'group2',index:5};
// let currentItemContent = Content[currentItem.type][currentItem.index];
let obj = [{content:"hello15"},{content:"world"}];
let newIndex = Content["group1"].indexOf(obj);
let type = "group1";
if(newIndex < 0)
{
type="group2"
console.log(Content["group2"]);
newIndex = Content["group2"].indexOf(obj);
}
console.log({"type":type,"index":newIndex});
expected: {type:'group2',index:5}
Loop through the Content object using for...in. Check if the given array is in each group by using findIndex. Since both the objects in the array seem to be in order, you can simply compare the string returned by JSON.stringify
let Content={group1:[[{content:"hello"},{content:"world"}],[{content:"hello1"},{content:"world"}],[{content:"hello2"},{content:"world"}],[{content:"hello3"},{content:"world"}],[{content:"hello4"},{content:"world"}],[{content:"hello5"},{content:"world"}]],group2:[[{content:"hello10"},{content:"world"}],[{content:"hello11"},{content:"world"}],[{content:"hello12"},{content:"world"}],[{content:"hello13"},{content:"world"}],[{content:"hello14"},{content:"world"}],[{content:"hello15"},{content:"world"}]]}
function find(input, search) {
for (const type in input) {
const group = input[type];
const index = group.findIndex(a => JSON.stringify(a) === JSON.stringify(search));
if (index != -1)
return { type, index }
}
return null
}
console.log(find(Content, [{content:"hello15"},{content:"world"}]))
console.log(find(Content, [{content:"hello"},{content:"world"}]))
You could also use Array.find in combination with Object.keys and Array.some. The array comparison you can do via JSON.stringify however remember that if your keys are in different order that would not work:
[{content:"world"},{content:"hello"}] vs [{content:"hello"},{content:"world"}]
would not match as you would expect since you are matching on strings and they are now different.
let Content = { group1: [ [{content:"hello"},{content:"world"}], [{content:"hello1"},{content:"world"}], [{content:"hello2"},{content:"world"}], [{content:"hello3"},{content:"world"}], [{content:"hello4"},{content:"world"}], [{content:"hello5"},{content:"world"}], ], group2: [ [{content:"hello10"},{content:"world"}], [{content:"hello11"},{content:"world"}], [{content:"hello12"},{content:"world"}], [{content:"hello13"},{content:"world"}], [{content:"hello14"},{content:"world"}], [{content:"hello15"},{content:"world"}], ], };
let findArray = (data, obj) => {
let index, group = Object.keys(data).find((k,i) => {
index = i
return data[k].some(x => JSON.stringify(x) === JSON.stringify(obj))
})
return { index, group }
}
console.log(findArray(Content, [{content:"hello"},{content:"world"}]))
console.log(findArray(Content, [{content:"hello10"},{content:"world"}]))

Issue in removing object using Lodash _remove

I am having an Object:
ids = [ "-LIof_e0hPtXKtkc4Uh9", "-LIjBcGO7m7VQ-B3pfYt" ]
If I Iterate using .map function of lodash
_.map(ids, (userID, key) => {
console.log('Lopping userId',userID);
})
it gives me value of each id.
Now when I am trying to remove it using _remove it is not working as expected.
_.remove(ids, (value, key, obj) => value == idToBeRemoved);
Still there is no difference in ids Object.
I am really new to angular4 and using lodash for the first time.
I just wanted to remove a value from ids object and get the remaining object.
Print of console.
I am using firebase and trying to delete data after retrieving it from firebase :
deleteTransactWith(transactWithKey,transactWithUser) {
let currentUser = this._authService.getLoggedInUser();
console.log(transactWithUser.groups)
console.log(Object.keys(transactWithUser.groups).length)
console.log('key To remove',transactWithKey)
for (var key in transactWithUser.groups) {
if (transactWithUser.groups.hasOwnProperty(key)) {
let group = this.firebase.object(`/url/${currentUser.$key}/${key}`);
group.snapshotChanges().take(1).subscribe((groupData: any) => {
groupData = groupData.payload.toJSON();
//console.log('not removed',groupData.userIds)
console.log('key',transactWithKey)
_.remove(groupData.userIds, (value) => value == transactWithKey);
//_.pull(groupData.userIds, transactWithKey);
console.log('removed',groupData.userIds)
});
}
}
You want _filter instead
const ids = [ "-LIof_e0hPtXKtkc4Uh9", "-LIjBcGO7m7VQ-B3pfYt" ]
const idToBeRemoved = "-LIof_e0hPtXKtkc4Uh9"
const filteredIds = _.filter(ids, function(id) { return id !== idToBeRemoved})
console.log(filteredIds)
You can simply use lodash _.pull
const _ = require("lodash");
const ids = [ "-LIof_e0hPtXKtkc4Uh9", "-LIjBcGO7m7VQ-B3pfYt" ]
const result = _.pull(ids, "-LIjBcGO7m7VQ-B3pfYt" )
console.log(filteredIds)
First find the index of what you are removed item and next pull out from it by _.pullAt(lodash)
let getIndex= _.findIndex(this.images, function(o) { return o.name == img.name; });
let removedImage = _.pullAt(this.images, getIndex) ;

Categories

Resources