2009-08-11 4 views
3

모두 C# 공급 업체에 Name 속성이있는 목록이 있습니다. 사용자가 이름을 검색하여 해당 목록을 필터링 할 수있게하려고합니다. 필터 문자열은 부분 일치 또는 완전한 일치 일 수 있습니다. 그러나 결과 목록에 정확한 일치가 포함 된 경우 목록의 부분 일치가 모두있는 목록의 위치가 0이어야합니다.목록에서 특정 요소가있는 목록의 하위 집합을 먼저 선택하십시오.

linq 및 lambdas를 사용하면 하위 목록을 쉽게 얻을 수 있지만 정확하게 일치하는 항목이 있으면 추가 한 다음 두 번째 목록을 만들지 않고 나머지 목록을 추가해야 할 필요가 있습니다. 정확한 것. 그것은 우아하지 않다. 더 쉬운 방법이 있습니까? (이 컴파일되지 않을 수도 있습니다 메모리에서 수행) 내 현재 코드 :

List<Vendor> temp = vendors.Where(v => v.Name.ToUpper().Contains(vendorNameSearch)).ToList(); 
Vendor exactMatch = vendors.Single(v => v.Name.ToUpper().Equals(vendorNameSearch)); 

if(null == exactMatch){return temp;} 
else 
{ 
    List<Vendor> temp1 = new List<Vendor>(); 
    temp1.Add(exactMatch); 
    temp1.AddRange(temp.Remove(exactMatch)); 
    return temp1; 
} 

답변

3

어떻게 Levenshtein 거리를 계산하는 StringComparer 개발에 대한 - 제로로 정확히 일치하는이 해야지을 - 그리고이에 의해 결과를 주문 오름차순. 이렇게하면 먼저 정확한 일치를 얻고 나머지 결과는 검색 문자열에 유사성 (적어도 하나의 측정 값)에 따라 정렬됩니다.

var list = vendors.Where(v => v.Name.ToUpper().Contains(vendorNameSearch)) 
        .OrderBy(v => ComputeLevenshtein(v.Name.ToUpper(), 
                vendorNameSearch)); 

또는 당신은 정확히 일치 int.MinValue되는 다른 모든 값()은 compareTo의 결과 인 물건을 주문하는 비교 자를 만들 수 있습니다. 또한 정확한 일치를 먼저 주문합니다.

1

나는 이것이하지만 여기에 또 다른 옵션이 얼마나 효율적으로 아무 생각, 문자열 길이의 절대 차이에 의해

List<String> strings = new List<String> {"Cat","Dog","Pear","Apple","Catalog"}; 

var results = (from st in strings 
    where st == "Cat" 
    select new {Priority = 1,st}).Union(

    from st in strings 
    where st.Contains("Cat") 
    select new {Priority = 2, st}).OrderBy(x => x.Priority).Select(x=> x.st).Distinct(); 
1

주문이 없습니다. (.. = 0 복근 차이) 정확한 일치, 다른 사람 동안 모두 0보다 큰 것 같은 길이 유일한 하나가 될 것입니다 :

var list = vendors.Where(v => v.Name.ToUpper().Contains(vendorNameSearch)) 
        .OrderBy(v => Math.Abs(v.Name.ToUpper().Length - vendorNameSearch.Length))); 

그것은 달리 임의의 순서가 될 것이다, 그러나 그것은 충족 당신의 주요 목표.

하지만 원래 코드와 같은 2 단계 솔루션에는 아무런 문제가 없습니다.

3

첫째, 저는 tvanfosson의 대답에서 사용성 관점에서 접근법을 좋아합니다.

그렇지 않으면 당신은 복합 종류를 사용하여 원하는 동작을 얻을 수 있습니다 정확한 일치 비교의 부울 결과로

vendors.Where(v => v.Name.ToUpper().Contains(vendorNameSearch)) 
     .OrderBy(v => !string.Equals(v.Name, vendorNameSearch)) 
     .ThenBy(v => v.Name) 
     .ToList(); 

주문은 정확히 일치가 먼저 나열되어 있는지 확인합니다. 부울 값이 정렬되는 방식으로 인해 정확히 일치하는 이름을 가진 공급 업체는 false 값을 가져야합니다. 문자열 동등성을 반전하는 대신 OrderByDescending을 사용하여이 작업을 수행 할 수도 있습니다.

관련 문제