【问题标题】:Set operation on a list of strings对字符串列表进行设置操作
【发布时间】:2013-10-23 22:21:17
【问题描述】:

我得到了一个字符串列表,我想做一个将每个项目与其余项目连接起来的操作。以下测试目前失败,我认为 join 不是我应该使用的正确 linq 方法 - 请告诉我如何完成此操作?输出的模式应该告诉投影应该如何,如果不是规则很简单:取一个项目并与所有其他项目连接,然后移动到下一个项目。下面测试:

[Test]
        public void Should_concatenate_all_items()
        {
            var items = new List<string> {"a", "b", "c", "d"};

            var concatenatedList = items .Join(items , x => x, y => y, (x, y) => string.Concat(x, y));

            foreach (var item in concatenatedList)
            {                
                //Should output:ab
                //Should output:ac
                //Should output:ad
                //Should output:bc
                //Should output:bd
                //Should output:cd
                Console.WriteLine(item);
            }
        }   

注意:我使用的是 .NET 3.5。

【问题讨论】:

  • 什么是potentialItems 及其元素?这是完整的输出还是样本?
  • 好吧,我就是这么想的
  • 为什么要使用 Linq 来做这样的事情?这只是一个嵌套循环,它已经完成了,并且在几个月的时间内,它在做什么将非常明显。 Linq 背后的理念是更大的表达力,无论如何都不能表达它的一切......

标签: c# linq


【解决方案1】:
var concatenatedList = (from i in items
                     from x in items
                     where i != x
                     select string.Concat(i, x)).ToList();

对于您列出的确切输出:

 var concatenatedList = (from i in items
                     from x in items
                     where i != x && items.IndexOf(i) < items.IndexOf(x)
                     select string.Concat(i, x)).ToList();

【讨论】:

  • 我给了另一个,写第一个时不清楚。
【解决方案2】:

我认为我的解决方案可能有点矫枉过正,但在现实世界中它可能更有帮助。另外,我在 Linq 中找不到干净的方法。 Linq 的 except 似乎不适合这个。

您可以使用 IEnumerator 为您枚举值。

public class ConcatEnum : IEnumerator
{
    public List<String> _values;

    // Enumerators are positioned before the first element 
    // until the first MoveNext() call. 
    int position1 = 0;
    int position2 = 0;

    public ConcatEnum(List<String> list)
    {
        _values = list;
    }

    public bool MoveNext()
    {
        position2 = Math.Max(position2 + 1, position1 + 1);
        if (position2 > _values.Count - 1){
            position1++;
            position2 = position1 + 1;
        }

        return position1 < _values.Count - 1;
    }

    public void Reset()
    {
        position1 = 0;
        position2 = 0;
    }

    object IEnumerator.Current
    {
        get
        {
            return Current;
        }
    }

    public String Current
    {
        get
        {
            try
            {
                return _values[position1] + _values[position2];
            }
            catch (IndexOutOfRangeException)
            {
                throw new InvalidOperationException();
            }
        }
    }

    public IEnumerator GetEnumerator()
    {
        this.Reset();
        while (this.MoveNext())
        {
            yield return Current;
        }
    }
}

这样称呼它:

var items = new List<string> { "a", "b", "c", "d" };
foreach (var i in new ConcatEnum(items))
{
    //use values here
}

【讨论】:

    【解决方案3】:

    你可以这样使用:

    var concatenatedList =
        from x in items.Select((str, idx) => new { str, idx })
        from y in items.Skip(x.idx + 1)
        select x.str + y;
    

    或者用流利的语法:

    var concatenatedList =
        items.Select((str, idx) => new { str, idx })
             .SelectMany(x => items.Skip(x.idx + 1), (x, y) => x.str + y);
    

    【讨论】:

    • +1。以下问题在这里使用了更多cross join 示例。
    猜你喜欢
    • 1970-01-01
    • 2021-06-27
    • 1970-01-01
    • 2016-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多