迭代在两个列表中

时间:2017-11-10 12:11:34

标签: c#

一周前我问了这个问题,现在我找到了一些我错过的东西。如果我重新开启这个问题,我不知道是否会得到任何答复,这就是我创建一个新问题的原因。最后一个条件不起作用。 我试图用不同的对象迭代两个列表。如果我在比较listTest1和listTest2时完成以下条件,我将记录添加到第三个列表

  • 如果abbrv和日期相同,我正在添加对象 listTest2 to listTest3
  • 如果abbrv相同,但日期不同,我正在添加 从listTest2到listTest3的对象,我正在切换完成的 财产到真。另外,我从listTest1添加记录 to listTest3。
  • 如果listTest2中不存在listTest1的abbrv,我正在添加 从listTest1到listTest3的记录。
  • 如果listTest2中的abbrv不存在于listTest2中。我补充说 从listTest2到listTest2的记录

我知道这听起来很混乱,这就是为什么我会告诉你我会得到什么以及我期待什么。

我收到了,测试6对象丢失了 enter image description here

class Program
{
    static void Main(string[] args)
    {
        Test1 test1 = new Test1() { abbrv = "Test1", date = new DateTime(2017, 11, 12), completed = false };
        Test1 test2 = new Test1() { abbrv = "Test2", date = new DateTime(2017, 12, 17), completed = false };
        Test1 test5 = new Test1() { abbrv = "Test5", date = new DateTime(2017, 12, 12), completed = false };

        Test2 test3 = new Test2() { abbrv = "Test1", date = new DateTime(2017, 11, 12), completed = false, abbrevName = "AbbrvName1" };
        Test2 test4 = new Test2() { abbrv = "Test2", date = new DateTime(2017, 12, 12), completed = false, abbrevName = "AbbrvName2" };
        Test2 test7 = new Test2() { abbrv = "Test5", date = new DateTime(2017, 12, 18), completed = false, abbrevName = "AbbrvName3" };
        Test2 test6 = new Test2() { abbrv = "Test6", date = new DateTime(2017, 12, 18), completed = false, abbrevName = "AbbrvName3" };
        List<Test1> listTest1 = new List<Test1>();
        List<Test2> listTest2 = new List<Test2>();
        List<Test2> listTest3 = new List<Test2>();
        listTest1.Add(test1);
        listTest1.Add(test2);
        listTest1.Add(test5);
        listTest2.Add(test6);
        listTest2.Add(test3);
        listTest2.Add(test4);
        listTest2.Add(test7);
        for (int i = 0; i < listTest1.Count; i++)
        {
            bool abbrvFound = false;
            for (int a = 0; a < listTest2.Count; a++)
            {
                if (listTest1[i].abbrv != listTest2[a].abbrv)
                {
                    continue;
                }

                abbrvFound = true;
                if (listTest1[i].date == listTest2[a].date)
                {
                    listTest3.Add(listTest2[a]);
                }
                else
                {
                    listTest3.Add(new Test2() { abbrv = listTest2[a].abbrv, date = listTest2[a].date, completed = true, abbrevName = listTest2[a].abbrevName });
                    listTest3.Add(new Test2() { abbrv = listTest1[i].abbrv, date = listTest1[i].date, completed = listTest1[i].completed, abbrevName = string.Empty });
                }
            }
            if (!abbrvFound)
            {
                listTest3.Add(new Test2() { abbrv = listTest1[i].abbrv, date = listTest1[i].date, completed = listTest1[i].completed, abbrevName = string.Empty });
            }
        }
        foreach (var test in listTest3)
        {
            Console.WriteLine(test.abbrv + " " + test.date + " " + test.completed + " " + test.abbrevName);
        }
        Console.Write(1);
    }
}

public class Test1
{
    public string abbrv { get; set; }
    public DateTime date { get; set; }
    public bool completed { get; set; }
}
public class Test2
{
    public string abbrv { get; set; }
    public DateTime date { get; set; }
    public bool completed { get; set; }
    public string abbrevName { get; set; }
}

3 个答案:

答案 0 :(得分:2)

我不确定我是否完全按照你陈述的条件,但你似乎加入了两个不同的名单。为此,您可能会发现以下LINQ全外连接很有帮助。

var leftJoin = from t1 in listTest1
    join t2 in listTest2 on t1.abbrv equals t2.abbrv into lj
    from s in lj.DefaultIfEmpty()
    select new Test2() {abbrv = t1.abbrv, date = t1.date, completed = t1.completed, abbrevName = s.abbrv};

var rightJoin = from t2 in listTest2
    join t1 in listTest1 on t2.abbrv equals t1.abbrv into rj
    from s in rj.DefaultIfEmpty()
    select t2;

var fullOuterJoin = leftJoin.Union(rightJoin);

答案 1 :(得分:0)

我会使用LINQ分隔检查存在的部分,以便查找存在于一个列表中而不在另一个列表中的对象。
然后将您的算法用于其余条件

这是一个示例,显示如何通过abbrv名称查找2个列表不共享的对象:

var result = listTest1.Where(l => !listTest2.Any(l2 => l2.abbrv == l.abbrv));
var result2 = listTest2.Where(l => !listTest1.Any(l1 => l1.abbrv == l.abbrv));

Console.WriteLine("objects that exist in list 1 and not list list 2, based on abbrv string");
foreach (var t in result)
{
    Console.WriteLine(t.abbrv);
}
Console.WriteLine("objects that exist in list 2 and not list list 1, based on abbrv string");
foreach (var t in result2)
{
    Console.WriteLine(t.abbrv);
}

执行此操作的输出将为:

objects that exist in list 1 and not list list 2, based on abbrv string
objects that exist in list 2 and not list list 1, based on abbrv string
Test6

答案 2 :(得分:0)

我建议使用MoreLINQ's FullJoin method

public static List<Data> GetResults(List<Data> list1, List<Data> list2)
{
    var joined = list1.FullJoin(list2, key1 => key1.Abbrv,
        firstSelector => new Data
        {
            Abbrv = firstSelector.Abbrv,
            Date = firstSelector.Date,
            Desc = firstSelector.Desc
        },
        secondSelector => new Data
        {
            Abbrv = secondSelector.Abbrv,
            Date = secondSelector.Date,
            Desc = secondSelector.Desc
        },
        (first, second) => new Data
        {
            Abbrv = second.Abbrv,
            Date = second.Date,
            Desc = second.Desc
        });

    var mem = joined.ToList();

    return mem;
}

<强>单元测试

[TestMethod]
public void FullTest()
{
    //arrange
    var listTest1 = GetTest1Data();
    var listTest2 = GetTest2Data();

    //act
    var res = Class1.GetResults(listTest1, listTest2);

    //assert
    //If the abbrv and the date is the same I am adding the object from listTest2 to listTest3
    //If the abbrv is the same but the date is different I am adding the object from listTest2 to listTest3 and I am switching the completed property to true.In addition, I am adding the record from listTest1 to listTest3.
    //If the abbrv from listTest1 doesn't exist in listTest2 I am adding the record from listTest1 to listTest3.
    //If the abbrv from listTest2 doesnt exist in listTest2.I am adding the record from listTest2 to listTest2
    var expected = new List<Data> { new Data { Abbrv = "InBothSameDate", Date = new DateTime(2017, 11, 12), Desc = "From2" },
        new Data{ Abbrv="InBothDifferentDate", Date = new DateTime(2017, 12, 12), Desc = "From2" },
        new Data{ Abbrv="OnlyIn1", Date = new DateTime(2017, 1, 1), Desc = "From1"  },
        new Data{ Abbrv="OnlyIn2", Date = new DateTime(2017, 1, 31), Desc = "From2"  }
    };

    //https://stackoverflow.com/questions/11055632/how-to-compare-lists-in-unit-testing
    CollectionAssert.AreEqual(res, expected);
}

Full Source Code