【问题标题】:Ordering a filtered list of objects according to the full list根据完整列表对过滤后的对象列表进行排序
【发布时间】:2017-09-12 22:27:06
【问题描述】:

我有一个List<object> fullList 和一个List<object> filteredList(只包含不同的项目,filteredList 中的所有项目都可以在fullList 中找到 - 但反之则不然)

现在有时在我的程序中我调用filteredList.Add(fullList[#]); 并意识到我想在filteredList 中保持与fullList 中存在的相同顺序。最好的方法是什么?

这是我想到的一个解决方案(但我想知道是否有更好的方法):

public void AddToFilteredList(object input)
{
    int index = 0;
    foreach (object ob in fullList)
    {
        if (filteredList.Contains(ob))
        {
            if (fullList.IndexOf(input) > fullList.IndexOf(ob))
                index++;
            else
            {
                filteredList.Insert(index, input);
                return;
            }
        }   
    }

    filteredList.Add(input);
}

【问题讨论】:

  • 保持排序
  • 使用 SortedList filteredList 或 List.Add(items[i]).Sort(x => x.currentSortAttribute) ...?
  • @mjwills 可以用多种不同的方式进行排序。基本上,我想知道是否有办法根据fullListfilteredList 进行排序。我不想弄清楚哪些属性对fullList 进行排序,然后根据这些相同的属性对filteredList 进行排序
  • @mjwills fullList 会随着时间而改变。它可以重新加载或以不同的方式排序。显然,在每种情况下,filteredList 都必须修改
  • @mjwills 没有。两个列表都不会有重复项。 fullList 只是事实,filteredList 因为我在放入之前检查它是否有物品

标签: c# list sorting


【解决方案1】:

fullList 会随着时间而改变。它可以重新加载或排序 不同。显然在每种情况下,filteredList 必须修改

如果fullList 可以随着时间的推移改变它的顺序,那么我鼓励你以稍微不同的方式思考这个问题。您不想要一个“排序列表”,而是“我的原始列表,但删除了一些项目”。

我建议声明:

HashSet<object> subsetOfFullList

并向其中添加条目,而不是向filteredList 添加条目。

然后,当您需要filteredList 时,使用Where(将维持秩序)(即时)生成它。比如:

using System;
using System.Collections.Generic;
using System.Linq;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            var fullList = new List<object> { 1, "bob2", "bob3", 4 };

            var subsetOfFullList = new HashSet<object> { fullList[3], fullList[1] };

            IReadOnlyList<object> filteredList = fullList.Where(z => subsetOfFullList.Contains(z)).ToList();

            Console.WriteLine(string.Join(",", filteredList));
            Console.ReadLine();
        }
    }
}

【讨论】:

  • 那么是Where在这里进行排序吗?
  • 不,您可以免费获得排序,因为Where 将按照它在fullList 中存在的顺序返回数据。我假设您并不想像“我的原始列表但删除了一些项目”那样需要“排序列表”。
  • 是的,这就是我要问的。 Where 是“排序”的,因为它按顺序通过fullList。这是一个有趣的方法。我想我会把那条线放在get 中作为filteredList,但这只是我
【解决方案2】:

我会创建一个包装类,并按照@L.B 的评论保持两个列表同步。这样添加的复杂性从O(n) 降低到O(log n)

public class MyList<T>
{
    List<T> _FullList = new List<T>();
    List<T> _FilteredList = new List<T>();

    public void Add(T item)
    {
        Insert(_FullList, item);
        if(somecondition)
            Insert(_FilteredList, item);
    }

    public void Remove(T item)
    {
        _FullList.Remove(item);
        _FilteredList.Remove(item);
    }

    void Insert(List<T> list, T item)
    {
        var index = list.BinarySearch(item);
        if (index < 0) index = ~index;
        list.Insert(index, item);
    }

    //other methods needed 
}

【讨论】:

    【解决方案3】:

    您可以将SortedList 用作您的filteredList,使用fullList 中的索引作为键:

    var fullListWithIndex = fullList.Select((f,i) => new { f, i });
    

    然后你可以过滤fullListWithIndex来保留索引:

    var filteredList = new SortedList<int, typeoff>();
    
    foreach (var fi in fullListWithIndex.Where(fi => test(fi.f)))
        filteredList.Add(fi.i, fi.f);
    

    然后你可以在filteredList的正确位置添加新项目:

    filteredList.Add(num, fullList[num]);
    

    您可以在之前使用filteredList 的地方使用filteredList.Values

    如果你喜欢扩展方法,ToSortedList 可以拥有:

    public static SortedList<TKey, TValue> ToSortedList<TObj, TKey, TValue>(this IEnumerable<TObj> src, Func<TObj, TKey> keySelector, Func<TObj, TValue> valueSelector) {
        var ans = new SortedList<TKey, TValue>();
    
        foreach (var srcObj in src)
            ans.Add(keySelector(srcObj), valueSelector(srcObj));
    
        return ans;
    }
    
    public static SortedList<TObj, TObj> ToSortedList<TObj>(this IEnumerable<TObj> src) => ToSortedList(src, x => x, x => x);
    public static SortedList<TKey, TObj> ToSortedList<TKey, TObj>(this IEnumerable<TObj> src, Func<TObj, TKey> keySelector) => ToSortedList(src, keySelector, x => x);
    

    现在你有

    var filteredList = fullListWithIndex.Where(fi => test(fi.f).ToSortedList(fi => fi.i, fi => fi.f);
    

    【讨论】:

      猜你喜欢
      • 2021-08-20
      • 2023-04-01
      • 2016-06-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-03
      • 2021-06-27
      相关资源
      最近更新 更多