I have a dynamically generated navigation structure shown. Each location has storetypes generated from the stores at the location.
I need to remove duplicates per location so that groceries can appear in both locations. I tried the common jquery solution below which removes duplicates but it results in each storetype appearing only in one location.
var seen = {};
$("ul#storetypes").find("li").each(function(index, html_obj) {
txt = $(this).text().toLowerCase();
if (seen[txt]) {
$(this).remove();
} else {
seen[txt] = true;
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul >
<li>Location 1
<ul id="storetypes" >
<li>groceries</li>
<li>cakes</li>
<li>motor spares</li>
<li>groceries</li>
</ul>
</li>
<li>Location 2
<ul >
<li>groceries</li>
<li>motor spares</li>
<li>motor spares</li>
<li>groceries</li>
</ul>
</li>
</ul>
CodePudding user response:
You can do it like this:
$("ul.sub-menu li").each(function(index, html_obj) {
if ($(this).prevAll(":contains(" $(this).text() ")").length > 0) {
$(this).remove();
}
});
This will look into each .sub-menu
and see if any 'li' exist already with the same text, and remove the duplicated.
Demo
$("ul.sub-menu li").each(function(index, html_obj) {
if ($(this).prevAll(":contains(" $(this).text() ")").length > 0) {
$(this).remove();
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul >
<li>Location 1
<ul id="storetypes" >
<li>groceries</li>
<li>cakes</li>
<li>motor spares</li>
<li>groceries</li>
</ul>
</li>
<li>Location 2
<ul >
<li>groceries</li>
<li>motor spares</li>
<li>motor spares</li>
<li>groceries</li>
</ul>
</li>
</ul>
CodePudding user response:
what you did is correct, but just do it for every <ul>
.
$("ul.storetypes").each(function() {
var seen = {};
$(this).find("li").each(function(index, html_obj) {
txt = $(this).text().toLowerCase();
if (seen[txt]) {
$(this).remove();
} else {
seen[txt] = true;
}
});
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul >
<li>Location 1
<ul >
<li>groceries</li>
<li>cakes</li>
<li>motor spares</li>
<li>groceries</li>
</ul>
</li>
<li>Location 2
<ul >
<li>groceries</li>
<li>motor spares</li>
<li>motor spares</li>
<li>groceries</li>
</ul>
</li>
</ul>
CodePudding user response:
To remove duplicates within each location, you can modify your code to keep track of the seen storetypes for each location, rather than globally. You can do this by adding a new object to keep track of seen storetypes for each location, and updating the code that checks for duplicates to use this object instead of the global seen object.
Here is an example of how you could modify your code to achieve this:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
<script>
// Create an object to keep track of seen storetypes for each location
var seen = {};
// Loop through all locations
$("ul.menu").find("li").each(function (index, html_obj) {
// Get the text of the current location
var location = $(this).text().toLowerCase();
// Initialize an empty array to keep track of seen storetypes for the current location
seen[location] = [];
// Loop through all storetypes in the current location
$(this).find("ul#storetypes").find("li").each(function (index, html_obj) {
// Get the text of the current storetype
var storetype = $(this).text().toLowerCase();
// Check if the current storetype has been seen in the current location
if (seen[location].indexOf(storetype) != -1) {
// If the storetype has been seen, remove it from the list of storetypes
$(this).remove();
} else {
// If the storetype has not been seen, add it to the list of seen storetypes for the current location
seen[location].push(storetype);
}
});
});
</script>
This code will keep track of the seen storetypes for each location, and remove any duplicates within each location. This will allow the same storetype to appear in multiple locations, but will remove any duplicates within a single location.
CodePudding user response:
You just need to target your top-level iteration at each sub-list.
Then iterate its children and remove duplicates.
Also, you don't need jQuery.
document.querySelectorAll(".sub-menu").forEach((list) => {
const seen = new Set();
list.querySelectorAll(":scope > li").forEach((item) => {
const text = item.textContent.trim();
if (seen.has(text)) {
item.remove();
} else {
seen.add(text);
}
});
});
<ul >
<li>Location 1
<ul id="storetypes" >
<li>groceries</li>
<li>cakes</li>
<li>motor spares</li>
<li>groceries</li>
</ul>
</li>
<li>Location 2
<ul >
<li>groceries</li>
<li>motor spares</li>
<li>motor spares</li>
<li>groceries</li>
</ul>
</li>
</ul>