查找两个列表中的常见项

时间:2017-06-16 09:26:42

标签: c# list

我的问题是我需要比较两个列表并找到共享相同字段值的对象数量。请找一个两个列表的常用对象,或者一些连接操作。我不想使用Linq,因为我需要访问元素的索引,但是现在这些类/方法已经简化了。 Pip类:

public class Pip{
    public CONTROLLER.COLORS Color;
}

简化类序列基本上是点数列表

public class Sequence{
    private List<Pip> pips = new List<Pip>();

    public Sequence(Pip[] pips)
    {
        for (int i = 0; i < pips.Length; i++)
        {
            addPip(pips[i]);
        }
    }
    public List<Pip> getPips()
    {
        return pips;
    }
}

所以现在我有这个方法,它会返回两个序列的相同颜色的点数,其中每个点都有一些颜色。

private int getMatchedColors(Sequence lockSeq, Sequence checkSeq)
{
    List<Pip> lockPips = lockSeq.getPips();
    List<Pip> checkPips = checkSeq.getPips();
    List<Pip> excludedPips = new List<Pip>(lockPips.Count);
    int matchedColors = 0;

    for (int i = 0; i < lockPips.Count; i++)
        for (int j = 0; j < checkPips.Count; j++)
            if (checkPips[i].Color == lockPips[j].Color && !excludedPips.Contains(lockPips[j]))
            {
                matchedColors++;
                excludedPips.Add(lockPips[j]);
                break;
            }
    return matchedColors;
}

逻辑开始我的理由是下一个。 获取lockPips列表的每个元素,并将当前点的颜色与checkPips&#39;的当前颜色进行比较。列表点。如果匹配,我们会检查是否匹配lockPips&#39;当前点已经过检查。如果没有,那么我们增加计数器并添加lockPips&#39;当前点到checkedPips列表,从而确保在下次检查时跳过它。

调试显示excludedPips列表已经包含第一次检查的点,并且它在每次检查时都使用它的颜色,从而使算法跳过&#34中的所有指令;如果&#34;言。

  

示例:lockPips:RED,GREEN,GREEN checkPips:RED,GREEN,GREEN   预期匹配的颜色:3个实际匹配的颜色:1(红色)

     

lockPips:BLUE,BLUE,BLUE checkPips:预期蓝色,蓝色,红色   matchedColors:2个匹配的实际颜色:1(蓝色)

因此,任何实际matchedColors&gt;的结果都是如此0是1。

2 个答案:

答案 0 :(得分:1)

您不必为此目的编写自己的逻辑,因为您可以使用LINQ和Intersect方法获得所需的结果。像这样:

List<Pip> excludedPips = lockPips.Intersect(checkPips).ToList();

同样在你班上:

public class Pip
{
    public string Color { get; set; }

    public override bool Equals(object obj)
    {
        if (!(obj is Pip))
            return false;
        Pip p = (Pip)obj;
        return (p.Color == Color);
    }
    public override int GetHashCode()
    {
        return String.Format("{0}", Color).GetHashCode();
    }
}

或者,如果您想获得两个List的常见对应元素,请使用Zip

List<Pip> excludedPips = lockPips.Zip(checkPips , (f,s) => f.Color == s.Color ? f : null)
                                  .Where(c => c!= null).ToList();

答案 1 :(得分:0)

你可以做这样的事情

List<Pip> Matches = new List<Pip>(L1);

// Get the matches
Matches.AddRange(L2.Except(Matches));
Matches.RemoveAll(pip=> !L2.Contains(pip));

然后,只要你想在匹配中找到所需点子的原始索引,就可以这样做

List<int> indexes = new List<int>();

if (L1.Contains(desiredPip)) indexes = Enumerable.Range(0, L1.Count).Where(i => L1[i].Color == desiredPip.Color).ToList();

if (L2.Contains(desiredPip)) indexes = Enumerable.Range(0, L2.Count).Where(i => L2[i].Color == desiredPip.Color).ToList();

我知道你说你不想使用LINQ,但如果你唯一的理由是你想要访问索引,这就解决了这个问题。