分割int的列表,并保留对原始元素C#的引用

时间:2020-09-21 12:42:28

标签: c# linq

我有一个整数列表:

List<int> foo = new List<int>() {1, 2, 3, 4, 5, 6, 7, 8};

我需要根据索引的奇偶性对它进行切片,所以:

List<int> bar1 = foo.Where((i, v) => v % 2 == 0).ToList();
List<int> bar2 = foo.Where((i, v) => v % 2 == 1).ToList();

问题是,如果我现在设置

bar1[0] = -1

原始的 foo 列表保持不变。 有什么变通办法可以更改 bar1 bar2 的值,同时还可以更改原始 foo 列表的值?

2 个答案:

答案 0 :(得分:2)

要保持所需的格式,我不建议您使用引用类型的对象来填充集合,例如,这将起作用

public class ReferenceInt
{
    public int Value { get; set; } = 0;
}

现在这可以工作:

List<ReferenceInt> foo = new List<ReferenceInt>()
{
    new ReferenceInt(){ Value = 1 },
    new ReferenceInt(){ Value = 2 },
    new ReferenceInt(){ Value = 3 },
    new ReferenceInt(){ Value = 4 },
    new ReferenceInt(){ Value = 5 },
    new ReferenceInt(){ Value = 6 },
    new ReferenceInt(){ Value = 7 },
    new ReferenceInt(){ Value = 8 }
};

现在您必须过滤参考对象内的每个值

List<ReferenceInt> bar1 = foo.Where(v => v.Value % 2 == 0).ToList();
List<ReferenceInt> bar2 = foo.Where(v => v.Value % 2 == 1).ToList();

,这更改了其中所有带有ReferenceInt的集合中的值。 所以foobar1都将显示相同的内容

bar1[1].Value = 17;

答案 1 :(得分:2)

您可以创建代理以在源列表和过滤视图之间工作。

public class Indexer<T> : IEnumerable<T>
{
    public T this[int index]
    {
        get => All().ElementAt(index);
        set
        {
            var i = 0;
            foreach (var item in _source)
                if (_filter(item))
                {
                    if (i++ == index)
                        _source[i] = value;
                    break;
                }
        }
    }

    public IEnumerable<T> All() => _source.Where(o => _filter(o));

    readonly IList<T> _source;
    readonly Func<T, bool> _filter;

    public Indexer(IList<T> source, Func<T, bool> filter)
    {
        _source = source;
        _filter = filter;
    }

    IEnumerator<T> IEnumerable<T>.GetEnumerator() => All().GetEnumerator();
    IEnumerator IEnumerable.GetEnumerator() => All().GetEnumerator();
}

此代理将谨慎处理索引并简化用法:

List<int> foo = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8 };
var bar1 = new Indexer<int>(foo, o => o % 2 == 0);
Console.WriteLine(string.Join(",", bar1)); // 2,4,6,8
bar1[0] = -1;
Console.WriteLine(string.Join(",", bar1)); // 4,6,8
Console.WriteLine(string.Join(",", foo));  // 1,-1,3,4,5,6,7,8