2012-09-03 7 views
2

각 항목이 항목 배열을 보유 할 수있는 프로그램에서 작업 중입니다. (저는 나무와 같은 구조의 메뉴를 만들고 있습니다)목록으로 C 재귀 프로그래밍

현재 항목이 있습니다. 목록 대신 배열을 사용하지만 코드를 단순화하기 위해 모든 기능을 사용하고있는 것처럼 느껴지지 않습니다. 인터페이스 (.add, .remove, etc ...)가 많은 의미를 가지기 때문에 표준 배열을 통해 목록을 선택했습니다.

구조를 검색하고 이름 경로 (즉, Item.subitem.subsubitem.subsubsubitem)를 반환하는 코드가 있습니다. 아래 코드는 다음과 같습니다.

public class Item 
{ 
                   //public Item[] subitem; <-- Array of Items 
    public List<Item> subitem;         // <-- List of Items 

    public Color itemColor = Color.FromArgb(50,50,200); 
    public Rectangle itemSize = new Rectangle(0,0,64,64); 
    public Bitmap itemBitmap = null; 
    public string itemName; 


    public string LocateItem(string searchName) 
    { 
     string tItemName = null; 

     //if the item name matches the search parameter, send it up) 
     if (itemName == searchName) 
     { 
      return itemName; 
     } 

     if (subitem != null) 
     { 

      //spiral down a level 
      foreach (Item tSearchItem in subitem) 
      { 
       tItemName = tSearchItem.LocateItem(searchName); 

       if (tItemName != null) 
        break; //exit for if item was found 
      } 
     } 


     //do name logic (use index numbers) 
     //if LocateItem of the subitems returned nothing and the current item is not a match, return null (not found) 
     if (tItemName == null && itemName != searchName) 
     { 
      return null; 
     } 

     //if it's not the item being searched for and the search item was found, change the string and return it up 
     if (tItemName != null && itemName != searchName) 
     { 
      tItemName.Insert(0, itemName + "."); //insert the parent name on the left --> TopItem.SubItem.SubSubItem.SubSubSubItem 
      return tItemName; 
     } 

     //default not found 
     return null; 
    } 


} 

목록으로 이것을 수행하는 더 쉬운 방법이 있다면 저의 질문은 무엇입니까? 목록이나 배열을 사용해야하는지에 대해 머리 속을왔다 갔다했습니다. 목록이있는 유일한 이유는 항목을 추가하거나 제거 할 때마다 배열 크기를 조정할 필요가 없기 때문입니다.

답변

2

목록이 큰 소리. 나는 당신의 정의에 대한 변형을 제안 할 것이다. 이 같은 클래스를 만들어보십시오 :

public class Item : List<Item> 
{ 
    public string Name; 
} 

을 당신이 자동으로 subitem 필드를 필요로하지 않고 그것을 트리를 만들 List<Item>에서 Item 상속을합니다.

다음은 클래스 내 전체 버전입니다 :

public class Item : List<Item> 
{ 
    public string Name; 

    private List<Item> LocateItems(string searchName) 
    { 
     if (this.Name == searchName) 
      return (new [] { this }).ToList(); 

     var result = 
      this 
       .Select(s => s.LocateItems(searchName)) 
       .Where(x => x !=null && x.Count > 0) 
       .FirstOrDefault(); 

     if (result != null) 
      result.Add(this); 

     return result; 
    } 

    public string LocateItem(string searchName) 
    { 
     var items = this.LocateItems(searchName); 
     if (items == null) 
      return null; 
     else 
      return String.Join(".", items.Select(i => i.Name).Reverse()); 
    } 
} 

일치와 부모의 모든 루트를 포함한 Item 경우 다음에 Item로 시작 Item의 목록을 반환 LocateItems 방법.

이 코드 테스트 :

var foos = new Item() { Name = "Foo" }; 
var bars = new Item() { Name = "Bar" }; 
var qazs = new Item() { Name = "Qaz" }; 
var wees = new Item() { Name = "Wee" }; 

foos.Add(bars); 
bars.Add(qazs); 
foos.Add(wees); 

Console.WriteLine(foos.LocateItem("Wee")); 
Console.WriteLine(foos.LocateItem("Qaz")); 
Console.WriteLine(foos.LocateItem("Bar")); 
Console.WriteLine(foos.LocateItem("Foo")); 

그리고 이러한 결과를 얻었다 :

Foo.Wee 
Foo.Bar.Qaz 
Foo.Bar 
Foo 
+0

난 (난 그냥 LINQ 물건에 받고 있어요)에 익숙하지 않은 해요 몇 줄이 있습니다를 . FirstOrDefault는 무엇을합니까? 또한. 카운트 계산이란 무엇입니까? 또한, 나는이 직선이 있는지 확인하기를 원하며, 각 레벨을 목록에 추가합니다. 그러면 목록에 역순으로 도트가 끝에 추가됩니다. 마지막으로 .Where 행을 SQL 데이터베이스와 같이 사용할 수 있습니까? –

+1

'FirstOrDefault' 확장 메소드는 시퀀스의 첫 번째 값을 반환하고 나머지는 무시하지만 시퀀스에 값이 없으면'null'을 반환합니다.이 경우에는 "검색시 첫 번째 일치 항목을 제공하거나 일치하는 항목이없는 경우 null"이라고 표시됩니다. 내 대답은'LocateItems' 메소드에 대해 설명했다. 목록의 첫 번째 항목은 리프 노드이므로 조인하기 전에이를 반대로해야합니다. 'Select'는 모든 하위 항목에 대한 재귀 적 검색을 수행하고'Where'는 우리의 모든 불일치를 필터링합니다 - 아주 데이터베이스 쿼리와 비슷하지만 메모리에 있습니다. – Enigmativity

+0

나는 그것이 더 쉽게 느껴지므로 접근 방식을 채택하고 있습니다. 그러나 한 가지에 대해 궁금합니다. 당신은 그. 선택은 모든 하위 항목에 대한 재귀 검색을 수행합니다. 내 원래 코드를 사용하면 '하위 항목'객체의 모든 항목을 검색하는 것이 포함됩니까? 그렇지 않으면 하위 항목 자체가 아닌 목록에 직접 포함 된 객체이기 때문입니까? –

2

이 경우 목록을 사용하는 것이 좋습니다. 성능이 문제가된다면 어레이가 더 나은 선택이 될 것입니다. 그렇다면 배열은 약간 빨라지지만 발견했을 때 유연성이 훨씬 떨어집니다.

사람들이 충분히 이야기하지 않는 한 가지는 단순성이 코드 구조화를위한 훌륭한 기반이라는 것입니다. 배열을 사용하는 것보다 목록을 사용하여 작성하고 유지하는 것이 더 간단하다면 목록을 사용하여 (다른 모든 것은 동일합니다) 완벽하게 맞습니다.

1

목록을 제안합니다. 배열에 항목을 추가/제거하면 메모리가 재 할당되므로 항목의 동적 컬렉션 (일반적으로 귀하의 경우라고 가정) 목록의 성능이 전반적으로 향상됩니다. 당신은에보고 싶을 수도 :

Array versus List<T>: When to use which?