Remove multiple elements from array - javascript

I'd like to remove multiple specific elements from my array before it displays. Here is the code I have but it results in none of the elements being displayed:
$('[data-fancybox]').on('click', function() {
var visibleLinks = $('.fancybox:visible');
$.fancybox.open( visibleLinks, {
//options go here
caption: function (instance, item) {
var caption, link, collectTags, tags, filterTags, filteredTags;
function format(tpl, binding) {
if (typeof binding != 'function') return format(tpl, function (_, name) {
return binding[name];
});
return tpl.replace(/\$(\w+)/g, binding);
}
caption = $(this).data('caption');
link = format('<br>See more pictures', item);
collectTags = $(this).parent().attr("class").split(' ');
function createTag(it) {
return format("<a href='$site$it'>$it</a>", {
site: (it == 'wedding' || it == 'concert') ? 'http://example.com/gallery/#filter=.' : 'http://example.com/gallery/#filter=.',
it: it
});
}
filterTags = ['churchevent', 'corporate'];
filteredTags = tags.filter(function(itm){return itm!== filterTags});
tags = $.map(collectTags, createTag);
return [].concat(caption ? [caption, link] : link).concat(filteredTags.slice(1).join(', ')).join('<br>');
}
}, visibleLinks.index( this ) );
return false;
});

I'm supposing that, since you wrote "remove multiple specific elements" you want to REMOVE filterTags.
If that's the case then change this:
filterTags = ['churchevent', 'corporate'];
filteredTags = tags.filter(function(itm){return itm!== filterTags});
tags = $.map(collectTags, createTag);
return [].concat(caption ? [caption, link] : link).concat(filteredTags.slice(1).join(', ')).join('<br>');
to this:
filterTags = ['churchevent', 'corporate'];
tags = $.map(collectTags, createTag);
filteredTags = tags.filter((item)=>{
for(tag in filterTags) if (item.indexOf(filterTags[tag]) != -1) return false;
return true;
});
return [].concat(caption ? [caption, link] : link).concat(filteredTags.slice(1).join(', ')).join('<br>');
else just use != -1 instead of == -1 in the filter method.

What is "tags" in the context of tags.filter? I'm assuming it is some array. In either case, your filter is checking that an item in tags is not equal to filterTags, an array. Of course a single item in an array won't be equal to an array, so this will always return true, thus not filtering anything.
I think you probably want something like:
filteredTags = tags.filter(function(itm){return filterTags.indexOf(itm) !== -1});

Are you speaking about this array?
filterTags = ['churchevent', 'corporate'];
filteredTags = tags.filter(function(itm){return itm!== filterTags});
// Of note, you are creating tags just below this code. Should you move it up?
// Or rename tags => collectionTags???
// Either way, the filter function you are using is not doing what you expect.
tags.filter(function(itm){
// itm will be whatever, I'm guessing a string of some sort like "churchevent"
// Now you are trying to compare a string like "churchevent" to the
// array filterTags.
// This is what is happening...
return itm !== ['churchevent', 'corporate'];
// What you want to do is this in ES5
return (filterTags.indexOf(itm) === -1);
// or this in ES6
return !filterTags.includes(itm);
// Note the bang in front.
// TRUE will put itm in the tags array, FALSE will not.
}
Also, please reference the filter function in MDN.
Filter Function (MDN)

Related

How to iterate over array to build a url?

I'm trying to fetch data based on the url.
Everything works except on: let urlFilters.
What I'm trying to do:
iterate over the array: filters (if it's not null)
save output in: let urlFilters
By now, the iteration seem to work. When I console.log(urlFilters) I get key-value-pairs like "filter=orange" or "filter=apple?". The problem: only the last key-value-pair is saved and thus used for the url.
My question: how can I save all the key-value-pairs from the iteration and use them all in the url?
const getInfo = async(filters, searchTerm) => {
let url = "";
let urlBasis = "/api/productInfo?";
let urlSearchTerm = "";
let urlFilters = "";
if (searchTerm.length !== 0) {
...
} else {
...
};
//problem
if (filters.length !== 0) {
filters.forEach((filterItem, index) => {
urlFilters = `filter=${filterItem.categoryUrl}${index === filters.length -1 ? "" : "&"}`
//console.log(urlFilters) -> "filter=orange" or "filter=apple&"
});
} else {
urlFilters = ""
};
try {
//problem urlFilters: shows only the last key-value pair
url = urlBasis + urlSearchTerm + `${searchTerm.length !== 0 && filters.length !== 0 ? "&" : ""}` + urlFilters
} catch (err) {
console.log(err);
}
};
I already tried to use .map instead of .forEach. I also tried to use the spread operator. But it didn't work and I'm a little stuck. Any suggestions (also for code improvement) are appreciated. Thanks a lot!
If I understand the question correctly, you can iterate over your array easier via .map and then merge the array into a single string using .join():
const data = [{url: "apple"}, {url: "banana"}]
const url = `http://myurl.com?${data.map(item => `filter=${item.url}&`).join('').slice(0, -1)}`
console.log(url)
Note that .slice() ist needed to cut the last & character off the string.
So I think my previous approach wasn't the best.
It seems as the URLSearchParams-API is a simpler approach when working with urls and params - at least with this solution the code works and looks cleaner.
Here is what I have now:
const getInfo = async (filters, searchTerm) => {
let url = "/api/productInfo?";
let params = new URLSearchParams();
if(searchTerm.length !== 0) {
//logic
};
if(filters.length !== 0) {
filters.forEach((filterItem) => {
params.append("filter", filters.categoryUrl);
});
};
try {
url = url + params;
console.log("url", url);
...
}
}

Merge and combine item into array based on property

I am trying to merge an object into an array. Based on the title of the object, if it already exists in the array I want to add the amount of the object into the existing amount.
For example:
let items = [{"title":"x","amount":1}, {"title":"y","amount":1}, {"title":"z","amount":1}];
let obj1 = {"title":"x","amount":2};
If obj1 is merged into items the expected output would be
[{"title":"x","amount":3}, {"title":"y","amount":1}, {"title":"z","amount":1}]
Here is the solution I've come up with so far, Its working but I feel like there has to be a more elegant solution out there.
mergeResponses(x){
var found = this.items.some(function (arr) {
return arr.title === x.title;
});
if(!found){
//item doesnt exist, add to array
this.items.push(x);
}else{
//item already exists, add amount to existing amount
let dupItem = this.items.find(function (y) {
return y.title == x.title;
});
dupItem.amount += x.amount;
}
}
Below is a direct translation of your requirements. It's slightly more elegant than your implementation in the sense that the lookup only needs to be performed once.
let items = [{"title":"x","amount":1}, {"title":"y","amount":1}, {"title":"z","amount":1}];
let item = {"title":"x","amount":2};
let existing = items.find(i => i.title === item.title);
if (existing) {
existing.amount += item.amount;
} else {
items.push(item);
}
console.log(items);
you can do like this also,I don't say that this the better way but this also one way to do this.
var xyz=items.find(function(item){
if(item.title==obj1.title)
return item;
});
if(xyz)
xyz.amount+=obj1.amount;
else
items.push(obj1);
you can do as :
var items = [{"title":"x","amount":1}, {"title":"y","amount":1}, {"title":"z","amount":1}];
var obj = {"title":"x","amount":3};
matches = _.filter(items, i => i.title === obj.title)
if (matches) {
_.forEach (
matches,
match => match.amount += obj.amount
)
} else {
items.push(obj)
}
console.log(JSON.stringify(items))

Javascript normal Array value and Array value created by match function comparison

I have issue with two type of arrays value comparison, here is
tagNames = [];
tagNames.push('61');
cmt_wrds = '‏‏61'.replace(/[`~!##$%^&*()_|+\-=?;:'",،؛«».<>\{\}\[\]\\\/]/gi, ' ').match(/\S+/g);
if ( tagNames[0] == cmt_wrds[0] ) { // issue is here
console.log('yes'); // --> nothing
};
If you log your variables you will see that they are a bit different. It puts
'\u200f'
symbol which is the Right-To-Left Mark.
var tagNames = [];
tagNames.push('61');
cmt_wrds = '‏‏61'.replace(/[`~!##$%^&*()_|+\-=?;\u200f:'",،؛«».<>\{\}\[\]\\\/]/gi, ' ').match(/\S+/g);
console.log(tagNames);
console.log(cmt_wrds);
console.log(tagNames[0] === cmt_wrds[0]); // returns false, because they are different
Batter use with some varibale to give ah input data It will solve your problem.
(function () {
tagNames = [];
tagNames.push('61');
var datas ="61";//variable declaration
cmt_wrds = datas.replace(/[`~!##$%^&*()_|+\-=?;:'",،؛«».<>\{\}\[\]\\\/]/gi, ' ').match(/\S+/g);
if ( tagNames[0] == cmt_wrds[0]) { // issue is here
console.log('yes'); // --> nothing
};
})()
If your show their length, here is the difference.
tagNames[0].length is 2
cmt_wrds[0].length is 4
tagNames = [];
tagNames.push('61');
cmt_wrds = '‏‏61'.replace(/[`~!##$%^&*()_|+\-=?;:'",،؛«».<>\{\}\[\]\\\/]/gi, ' ').match(/\S+/g);
if ( tagNames[0] == cmt_wrds[0] ) { // issue is here
console.log('yes'); // --> nothing
};
console.log(tagNames[0].length);
console.log(cmt_wrds[0].length);

Jquery remove entry from array based on partial match

My array looks like this:
"MODE:ID:A:B"
["add:123456789:0:0", "del:99887766:0:0", "edit:1471872633890:8845:0", "add:4875125862:1523:NE"]
When a user deletes a row from a table a del entry is added to the array.
If the user has added a new entry to the table a add entry is added to the array.
If the user edits an entry an edit entry is added to the array.
The issue I have is if the user adds and then deletes the same row, I end up with two entries:
["add:123456789:0:0", "del:123456789:0:0"]
How can I get the del to overwrite the add (and/or) edit entry matching on the ID ?
I've tried:
rows = rows.map(function(value) {
if( value.indexOf(id) > -1 ) {
return false;
}
return value;
});
but that just replaces the entry with 'false' it doesn't delete it.
Any idea how I can do this ?
Thanks
jQuery.map will work as you expect. undefined or null return values will not be mapped.
rows = $.map(rows, function(value) {
if( value.indexOf(id) > -1 ) {
return undefined;
}
return value;
});
jQuery map callback function can return:
the translated value, which will be mapped to the resulting array
null or undefined, to remove the item
an array of values, which will
be flattened into the full array
You could iterate the array and split an item for the check and update and reassemble the item for an assingment to the element.
This proposal expects only one item with the given id.
var data = ["add:123456789:0:0", "del:99887766:0:0", "edit:1471872633890:8845:0", "add:4875125862:1523:NE"],
id = '123456789';
data.some(function (a, i, aa) {
var item = a.split(':')
if (item[1] === id) {
item[0] = "del";
aa[i] = item.join(':');
return true;
}
});
console.log(data);
You can just add a filter in the end:
rows = rows.map(function(value) {
if( value.indexOf(id) > -1 ) {
return false;
}
return value;
})
.filter( function(item) {return item;});
Try using this
rows = $.map(rows, function(value){
if(value.indexOf(id) > -1){
return 'del:' + id;
}
}

Return Object in Array if Property Match

Here is the scenario:
There is a parameter titledlistOfSelectedProductIdsthat contains
all of the selected ids.
There is another list titled listOfAllPossibleProducts, which
contains a list of objects. That object contains a ProductId,
ProductName, and ProductCode. It looks something like this:
The task at hand:
I need to loop through my listOfSelectedProductIds. If the ProductId matches a ProductId from listOfAllPossibleProducts, then I need to return that object.
Here is what I am doing:
function SelectedProducts(listOfSelectedProductIds){
for (var index = 0; index < listOfSelectedProductIds.length; index++) {
var currentItem = listOfSelectedProductIds[index];
var desiredProduct = _.contains(listOfAllPossibleProducts, currentItem);
if (desiredProduct === true) {
return listOfAllPossibleProducts[index];
}
}
}
What's currently happening:
My loop is getting the selected id as expected i.e. currentItem, but _.contains(...)
always returns false.
Question:
What is the best way to find the objects in
listOfAllPossibleProducts that have ProductIds that match my
ProductIds in the listOfSelectedProductIds
How about using _.filter:
var result = _.filter(listOfAllPossibleProducts, function (el) {
return _.contains(listOfSelectedProductIds, el.id);
});
Or the non-underscore method:
var result = listOfAllPossibleProducts.filter(function (el) {
return listOfSelectedProductIds.indexOf(el.id) > -1;
});
DEMO
create another structure productsByProductId once!
var productsByProductId = {};
listOfAllPossibleProducts.forEach(p => {
productsByProductId[p.ProductId()] = p
});
and maybe a helper function
function getProductById(id){
return productsByProductId[id];
}
and use this to map the ids to the nodes
var selectedProducts = listOfSelectedProductIds.map(getProductById)

Categories