C# 查找列表中所有元素的更有效方法
我得到了这个密码:C# 查找列表中所有元素的更有效方法,c#,.net,list,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].E
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;
顺便说一句,可能还有一些其他对象(如Details)扩展了MainDetails并需要此验证。
因此,这段代码将被多次使用。简单改进:
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;
}
如果你只在一个地方做这件事,我就不会再麻烦了。如果你在几个地方做同样的事情,你可以考虑设置一个函数,把你的<代码>细节>代码>转换成另一个<代码>列表<代码>,然后用“代码>顺序等于/<代码>进行比较。
<>编辑:虽然我越认为,把一个扁平的字符串列表和一个类层次结构中的一个比较起来似乎是个坏主意,但这里有一个例子,说明了如何以可扩展的方式来实现这一点。基类“使用”前两个值,然后交给派生类检查其余值:
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;
类的详细信息
{
字符串Attr1{get;set;}
字符串Attr2{get;set;}
受保护的虚拟布尔匹配(IEnumerator e)
{
//检查前两项是否存在并匹配
回来
e、 MoveNext()&e.Current.Equals(Attr1)&&
e、 MoveNext()和&e.Current.Equals(Attr2);
}
公共布尔匹配(IEnumerable详细信息)
{
使用(var e=details.GetEnumerator())
{
//检查详细信息是否匹配。(可选检查
//没有“额外”细节。)
返回匹配项(e);/&&!e.MoveNext();
}
}
}
课程详情:MainDetails
{
字符串Attr3{get;set;}
字符串Attr4{get;set;}
字符串Attr5{get;set;}
受保护的覆盖布尔匹配(IEnumerator e)
{
//检查MainDetails是否匹配,以及接下来的三个。
返回base.Matches(e)&&
e、 MoveNext()&e.Current.Equals(Attr3)&&
e、 MoveNext()&e.Current.Equals(Attr4)&&
e、 MoveNext()和&e.Current.Equals(Attr5);
}
}
...
列表值=getValues();
Details detailsData=getDetails();
如果(详细信息数据匹配(值))
返回true;
我不确定您的确切用例,但希望这能给您一些想法。如果您不能将所有属性都更改为一个数组,那么您至少可以将代码编写得更漂亮一些。。。虽然这是非常主观的
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;
}
List values=getValues();
Details detailsData=getDetails();
如果
(
值[0]。等于(detailsData.Attr1)&&
值[1]。等于(detailsData.Attr2)&&
值[2]。等于(detailsData.Attr3)&&
值[3]。等于(detailsData.Attr4)&&
值[4]。等于(detailsData.Attr5)
)
{
返回true;
}
当您的属性被命名为那样的名称时,没有“更清晰”的方法可以做到这一点。您可以使用反射(保存2行代码),但这会影响性能问题。我会说
List<string> values = getValues();
Details detailsData = getDetails();
if (values.SequenceEqual(new[] { detailsData.Attr1, detailsData.Attr2, detailsData.Attr3, detailsData.Attr4, detailsData.Attr5, }))
return true;
List values=getValues();
Details detailsData=getDetails();
if(values.SequenceEqual(新[]{detailsData.Attr1,detailsData.Attr2,detailsData.Attr3,detailsData.Attr4,detailsData.Attr5,}))
返回true;
这使用了LINQ的
SequenceEqual
扩展方法,除Rawlings答案外,请参见。。将详细信息对象转换为列表的函数可以如下所示:
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;
}
私有静态IEnumerable GetDetailProperties(详细信息){
收益率回报详情1;
收益率回报详情2;
收益率返回详情。3;
收益率回报详情。4;
收益率返回详情。5;
}
您可以使用SequenceEquals方法来比较这两个列表。如果您希望在使用它的地方有一个干净的代码,您可以在类中放置一些索引器
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;
for(int i=0;i<5;i++)
{
如果(值[i]!=detailsdata[i+1])
返回false;
}
返回true;
同样,只需在类上放置一个方法,如GetAtttributValue(inti) 听起来您的AttrN属性应该集中在一个数组中。然后您可以循环它。列表将始终具有计数
5
?所有的成员都是Attr1
,Attr2
等等类型的string
?我们可以看看Details类吗?问题是Details是MainDetails的一个子类,有些属性属于超类,所以很难将所有AttrN放在一个数组中/listArgh比我快几秒钟。:)
for(int i = 0; i < 5; i++)
{
if(values[i] != detailsdata[i+1])
return false;
}
return true;