I tried to make a function looking for elements that don't have class "check", in this case I got it. Then I wanted to push them into an array so I got length, but what I got wasn't what I expected, do you have any solution for this case?
PLESAE READ MY COMMENTS IN THE CODES
What i wanted is to get the length of list that does not have class "check"
const countUnactiveList =()=> {
let list = [...todoList.children];
let listArr = [];
list.filter(child => {
if(!child.classList.contains('check')) {
console.log(child); //it works, i got the lists that does not have class "check"
listArr.push(child);
console.log(listArr.length); //the output are 1 2 3 creeping down. But it should be 3
}
});
}
Array.prototype.filter returns a new array and you're logging the length in each iteration.
here's the fixed code:
const countUnactiveList = () => {
const list = [...todoList.children];
const listArr = list.filter(child => {
return !child.classList.contains('check');
});
console.log(listArr, listArr.length);
return listArr.length;
}
based on the function name, I think you're just interested in the count. You can return the length of the filtered array.
An alternate approach using reduce:
const countUnactiveList = () => {
const list = [...todoList.children];
return list.reduce((count, child) => {
if(!child.classList.contains('check')) {
count += 1;
}
return count;
}, 0)
};
Related
forecasts is array who has a 10 elements when ı try to print its work perfectly when ı use innerHtml its giving the last value of items and everything is look same
const getOtherDays = (data) => {
data.forecasts.forEach((forecast)=>{
for(var i = 0; i < day.length; i++) {
items = forecast.day;
console.log(items)
day[i].innerHTML = `${items}`
}
})
}
You shouldn't use a nested loop. If each element of data.forecasts is for a different day, use the index in that array to assign to the corresponding DOM element.
const getOtherDays = (data) => {
data.forecasts.forEach((forecast, i) => {
items = forecast.day;
console.log(items)
day[i].innerHTML = `${items}`
})
}
You are looping over the elements and setting it to the forecast of the day on every one. You want to select the specific element. The forEach index has the index. Hopefully that index matches the day in your elements. Basic idea:
const getOtherDays = (data) => {
data.forecasts.forEach((forecast, index)=>{
items = forecast.day;
day[index].innerHTML = `${items}`;
})
}
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))
I hava a problem with copy a objects to array. I think it is an problem with reference.
In my program i have few array. First is dataForMonth - it is array of objects with data for month. And second is an products array which contains products objects. Product have property forecastArry wchich is array of objects.
Here code :
this.allProducts.map(function (product) {
var dataForMonth = data.filter(function (e) {
return e.dataId === product.productDataId;
});
var z = { posId: product.sales_plan_pos_id, arry: [] }
for (var sheetMonth of sheet.channels) {
var result = dataForMonth.filter(function (e) {
return e.CHANNEL === sheetMonth.CHANNEL;
});
product.forecastArry[someId].channels = result;
);
The problem is that the every changed channels property have the same value - its a value from last product?
Anybody know how to fix it ?
Seems like you want to edit each product in this.allProducts. So you want to add a return value to your map. You should also use let so that the scope of variables declared is preserved within map function, although I believe the map function already takes care of that. In addition, not that you have to reassign this.allProducts to your map function call. So your answer should be something like the following:
this.allProducts = this.allProducts.map(function (product) {
let dataForMonth = data.filter(function (e) {
return e.dataId === product.productDataId;
});
let channelsForMont = [];
let z = { posId: product.sales_plan_pos_id, arry: [] }
for (let sheetMonth of sheet.channels) {
let result = dataForMonth.filter(function (e) {
return e.CHANNEL === sheetMonth.CHANNEL;
});
product.forecastArry[someId].channels = channelsForMont;
return product;
);
P.S Your original code has some missing brackets and result variable is unused. You should do something about them.
I'm wanting to filter an array without changing the original array that I've sliced from. You can see that the first thing I do within the filterChange function is to splice from the original array. The original array still ends up changed as well and I don't understand why.
var MenuDisplayModule = (function ($, window, document, Handlebars) {
var module = {};
module.menuItems = [];
module.init = function () {
console.info('BreadcrumbDisplayModule Init');
};
module.template = function (array) {
module.menuItems = array;
var filteredMenuItems = array.slice(0);
_template(filteredMenuItems);
}
module.filterChange = function (filterText) {
var filteredMenuItems = module.menuItems.slice(0);
filteredMenuItems.forEach(function (item, index) {
var filteredItems = item.MenuItems.filter(function (el) {
return (el.MenuText.includes(filterText));
});
filteredMenuItems[index].MenuItems = filteredItems;
})
_template(filteredMenuItems);
}
function _template(filteredMenuItems) {
var menu_items_source = $("#menu-items-template").html();
var menu_items_template = Handlebars.compile(menu_items_source);
$("#menu-items-placeholder").empty().html(menu_items_template({ menuItems: filteredMenuItems }));
}
return module;
}(window.jQuery, window, document, window.Handlebars));
So it appears I didn't understand splice. Specifically the shallow aspect of it. Since I was wanting to filter on a sub array of the array I was trying to copy I ended up not getting an actual copy.
Instead of copying the array I'm creating a new array and pushing the results of the filter to it. Taking with it the un-filtered properties from the original array.
module.filterChange = function (filterText) {
var filteredMenuItems = [];
module.menuItems.forEach(function (item, index) {
var filteredItems = item.MenuItems.filter(function (el) {
return (el.MenuText.includes(filterText));
});
filteredMenuItems.push({
HeaderText: item.HeaderText,
ID: item.ID,
MenuItems: filteredItems
})
})
_templateOnChange(filteredMenuItems);
}
If you want to filter the Array and create a new one with the filtered contents and leave the old one unchanged I suggest
newArray = oldArray.filter(function(item) { return item.wantThis === true; })
Now you have newArray consisting of only those Objects which have property
item.wantThis === true
In you example you are using slice() which in my experience looks very much like splice() (which will can mutate the Array).
I suggest you simply stick to using filter().
But why are you making so many slice copies?
It would help if you posted an example of an Object in the array you receive.
Form looking at you example it seems that filteredItems is a private var to the previous ForEach loop, if you change that active part of your code to....
module.filterChange = function (filterText) {
var filteredMenuItems = module.menuItems.slice(0);
var filteredItems; // declare the var outside of the .forEach
filteredMenuItems.forEach(function (item, index) {
filteredItems = item.MenuItems.filter(function (el) {
return (el.MenuText.includes(filterText));
});
filteredMenuItems[index].MenuItems = filteredItems;
})
_template(filteredMenuItems);
}
It might work.
The effect of your filteredItems is..
filteredMenuItems.forEach(function(item) {
item.MenuItems = item.MenuItems
.filter(function(el) { return (el.MenuText.includes(filterText)); });
})
So your item.MenuItems will get smaller with each filter.
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)