查找List中所有元素的更有效方法

时间:2013-02-26 11:57:10

标签: c# .net list

我收到了这段代码:

List<string> values = getValues();
Details detailsData = getDetails();

if (values[0].Equals(detailsData.Attr1))
    if (values[1].Equals(detailsData.Attr2))
        if (values[2].Equals(detailsData.Attr3))
            if (values[3].Equals(detailsData.Attr4))
                if (values[4].Equals(detailsData.Attr5))
                    return true;

getValues()返回一个字符串列表,我希望(^^)出现在Details对象上。

上面实现此代码是否有更高效或更“漂亮”的方式?

修改

 class Details : MainDetails
{
    string Attr3{ get; set; }
    string Attr4{ get; set; }
    string Attr5{ get; set; }
}

 class MainDetails
{
    string Attr1{ get; set; }
    string Attr2{ get; set; }
}

顺便说一下,可能还有一些像Details这样的其他对象扩展了MainDetails并要求进行验证。 所以这是代码将被多次使用。

6 个答案:

答案 0 :(得分:4)

简单改进:

if (values[0].Equals(detailsData.Attr1) &&
    values[1].Equals(detailsData.Attr2) &&
    values[2].Equals(detailsData.Attr3) &&
    values[3].Equals(detailsData.Attr4) &&
    values[4].Equals(detailsData.Attr5))
{
    return true;
}

如果你只是在一个的地方这样做,我就不会再打扰了。如果你在几个的地方做同样的事情,你可以考虑设置例如将Details转换为另一个List<string>然后使用例如SequenceEquals进行比较的功能class MainDetails { string Attr1 { get; set; } string Attr2 { get; set; } protected virtual bool Matches(IEnumerator<string> e) { // Check the first two items exist and match return e.MoveNext() && e.Current.Equals(Attr1) && e.MoveNext() && e.Current.Equals(Attr2); } public bool Matches(IEnumerable<string> details) { using (var e = details.GetEnumerator()) { // Check the details match. (Optionally check // that there are no "extra" details.) return Matches(e); // && !e.MoveNext(); } } } class Details : MainDetails { string Attr3 { get; set; } string Attr4 { get; set; } string Attr5 { get; set; } protected override bool Matches(IEnumerator<string> e) { // Check the MainDetails match, and the next three too. return base.Matches(e) && e.MoveNext() && e.Current.Equals(Attr3) && e.MoveNext() && e.Current.Equals(Attr4) && e.MoveNext() && e.Current.Equals(Attr5); } } ... List<string> values = getValues(); Details detailsData = getDetails(); if (detailsData.Matches(values)) return true;

编辑:虽然我越是考虑它,但是将字符串的平面列表与类的层次结构中的一个进行比较似乎是一个坏主意,这里有一个如何以可扩展的方式执行此操作的示例。基类“消耗”前两个值,然后切换到派生类以检查余数:

{{1}}

我不确定你的确切用例,但希望这个migth给你一些想法。

答案 1 :(得分:2)

如果你不能将你的属性更改为数组中的所有属性,那么你至少可以更好地编写代码......虽然这非常主观!

List<string> values = getValues();
Details detailsData = getDetails();

if
(
    values[0].Equals(detailsData.Attr1) &&
    values[1].Equals(detailsData.Attr2) &&
    values[2].Equals(detailsData.Attr3) &&
    values[3].Equals(detailsData.Attr4) &&
    values[4].Equals(detailsData.Attr5)
)
{
    return true;
}

答案 2 :(得分:1)

如果你想要一个干净的代码,你可以在你的课上放一些索引器。

    class Details : MainDetails
    {
        string Attr3 { get; set; }
        string Attr4 { get; set; }
        string Attr5 { get; set; }

        public override string this[int index]
        {
            get
            {
                switch (index)
                {
                    case 3:
                        return Attr3;
                    case 4:
                        return Attr4;
                    case 5:
                        return Attr5;
                }
                return base[index];
            }
        }
    }

    class MainDetails
    {
        string Attr1 { get; set; }
        string Attr2 { get; set; }

        public virtual string this[int index] 
        {
            get
            {
                switch (index)
                {
                    case 1:
                        return Attr1;
                    case 2:
                        return Attr2;
                    default:
                        throw new NotImplementedException();
                }
            }
        }
    }

这样你可以使用for循环进行比较

for(int i = 0; i < 5; i++)
{
   if(values[i] != detailsdata[i+1])
      return false;
}
return true;
只需在像GetAtttributValue(int i)这样的类上放置一个方法就可以实现同样的效果;

答案 3 :(得分:0)

当您的属性被命名为这样时,没有“更清晰”的方法。您可以使用反射(以保存2个代码行),但这会遇到性能问题。

答案 4 :(得分:0)

我会说像

List<string> values = getValues();
Details detailsData = getDetails();

if (values.SequenceEqual(new[] { detailsData.Attr1, detailsData.Attr2, detailsData.Attr3, detailsData.Attr4, detailsData.Attr5, }))
    return true;

这使用LINQ的SequenceEqual扩展方法,请参阅MSDN: Enumerable.SequenceEqual<TSource>

答案 5 :(得分:0)

除了罗林斯的回答。将Details-object转换为列表的函数可能如下所示:

private static IEnumerable<string> GetDetailProperties(Details details) {
    yield return details.Attr1;
    yield return details.Attr2;
    yield return details.Attr3;
    yield return details.Attr4;
    yield return details.Attr5;
}

您可以使用SequenceEquals方法比较两个列表。