# Using FeatureIDsToExclude

**URL:** <https://community.thinkgeo.com/t/using-featureidstoexclude/10397>\
**Category:** WinForms\
**Created:** [November 30, 2023, 3:56pm UTC](https://community.thinkgeo.com/t/using-featureidstoexclude/10397 "2023-11-30T15:56:25Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jonathan3](https://community.thinkgeo.com/letter_avatar_proxy/v4/letter/j/c68b51/32.png) [@Jonathan3](https://community.thinkgeo.com/u/Jonathan3)\
**Post date:** [November 30, 2023, 3:56pm UTC](https://community.thinkgeo.com/t/using-featureidstoexclude/10397/1 "2023-11-30T15:56:25Z")

</div>

Hi,

I thought it might be worth sharing something I found as (a) it might be helpful and (b) you might spot a problem with the method.

Essentially in our overridden variants of GetAlllFeaturesCore and GetFeaturesInBoundingBoxCore we added some code to handle excluded IDs and this made a significant performance improvement when excluding larger numbers of IDs. If we didn’t do this they were still excluded but it took much longer to draw the map.

CODE: SNIPPIT

> ```
> ` if (this.FeatureIdsToExclude.Count > 0) {
> List<string> wanted = features.Select(
> x => x.Id).ToList().Except(this.FeatureIdsToExclude).ToList();
> return new Collection<Feature>(features.Where(x => wanted.Contains(x.Id)).ToList());
> }`
> 
> ```

---

<div class="post-metadata">

**Author:** ![Jonathan3](https://community.thinkgeo.com/letter_avatar_proxy/v4/letter/j/c68b51/32.png) [@Jonathan3](https://community.thinkgeo.com/u/Jonathan3)\
**Post date:** [December 1, 2023, 10:02am UTC](https://community.thinkgeo.com/t/using-featureidstoexclude/10397/2 "2023-12-01T10:02:54Z")

</div>

A quick extra note: The above was broadly correct but not totally so, as it worked well when the number to exclude was a large proportion of the total number but very inefficiently when reversed. I did some rework to create a custom Comparer for the Exclude that also simplified it a bit.

---

<div class="post-metadata">

**Author:** ![Ben](https://community.thinkgeo.com/user_avatar/community.thinkgeo.com/ben/32/25720_2.png) [@Ben](https://community.thinkgeo.com/u/Ben)\
**Post date:** [December 5, 2023, 5:07pm UTC](https://community.thinkgeo.com/t/using-featureidstoexclude/10397/3 "2023-12-05T17:07:28Z")

</div>

Hi Jonathan,

Thanks for your suggestion! I logged it down and we will apply your suggestion to the future versions.

Also, I think we can make a couple improvements upon your code, please have a look see if it make sense:

```
        if (this.FeatureIdsToExclude.Count > 0)
        {
            // avoid using ToList(), to
            // 1, avoid creating Lists to save some memory
            // 2, delay the enumerating to the foreach statement where it is really needed. 
            var wantedEnumerable = features.Select(x => x.Id).Except(this.FeatureIdsToExclude);

            // use HashSet which has O(1) for Contains, instead of List<string) which has O(n) for Contains
            var wanted = new HashSet<string>();
            foreach (var feature in wantedEnumerable)
                wanted.Add(feature);
            return new Collection<Feature>(features.Where(x => wanted.Contains(x.Id)).ToList());
        }

```

Also, just let you know the latest product release v13.2.\* is now available on nuget. Please upgrade to that version if you are on beta.

Thanks,  
Ben

---

<div class="post-metadata">

**Author:** ![Jonathan3](https://community.thinkgeo.com/letter_avatar_proxy/v4/letter/j/c68b51/32.png) [@Jonathan3](https://community.thinkgeo.com/u/Jonathan3)\
**Post date:** [December 6, 2023, 2:03pm UTC](https://community.thinkgeo.com/t/using-featureidstoexclude/10397/4 "2023-12-06T14:03:36Z")

</div>

Thanks Ben, that was very helpful. Prior to that I had done some rework and ended up with something a bit different again:

The bit to process the list/collection is split out and looks like this:

> ```
> // Use FeatureIDsToExclude to strip out unwanted features from the return
> private Collection<Feature> AllowForExclusions(Collection<Feature> features)
> {
> var filteredApps = features.Except(FeatureIdsToExclude.Select(x => new Feature { Id = x }), new FeatureComparer());
> return new Collection<Feature>(filteredApps.ToList());
> }
> 
> ```

And then had this as the comparer:

> ```
> /// <summary>
> /// Class to manage comparing Fetaures on the bases that if the IDs are equal than they are the same feature.
> /// </summary>
> /// <remarks>
> /// Will be used by LINQ .Except operator to manage excluding unwanted features based on a list of IDs
> /// </remarks>
> class FeatureComparer : IEqualityComparer<Feature>
> {
> /// <summary>
> /// Straight forward string compare on IDs
> /// </summary>
> /// <param name="f1"></param>
> /// <param name="f2"></param>
> /// <returns></returns>
> public bool Equals(Feature f1, Feature f2)
> {
> return string.Equals(f1.Id, f2.Id);
> }
> 
> /// <summary>
> /// Returns hash code of just the ID, needed by LINQ .Exclude
> /// </summary>
> /// <param name="f"></param>
> /// <returns></returns>
> public int GetHashCode(Feature f)
> {
> return f.Id.GetHashCode();
> } }
> 
> ```

---

<div class="post-metadata">

**Author:** ![Ben](https://community.thinkgeo.com/user_avatar/community.thinkgeo.com/ben/32/25720_2.png) [@Ben](https://community.thinkgeo.com/u/Ben)\
**Post date:** [December 7, 2023, 11:28pm UTC](https://community.thinkgeo.com/t/using-featureidstoexclude/10397/5 "2023-12-07T23:28:11Z")

</div>

I’ve never used IEqualityComparer before, thanks for sharing, Jonathan!
