2015-10-14 8 views
1

У меня есть список элементов, и я проверяю, существует ли элемент в списке. Если он существует, я пытаюсь его найти.Найти объект, если он существует

Я думаю, что у этого есть немного накладных расходов, потому что я в настоящее время делаю два прохода над списком. Можно ли сделать за один проход?

В настоящее время у меня есть.

public partial class Item 
{ 
    public string text; 
    public int id; 
} 
.... 
static List<Item> data = new List<Item>(); 
static stub = new Item() { text = "NaN", id = -1 }; 
public static Item Get(int targetId) 
{ 
    if (data.Any(f => f.id == targetId) == false) 
    { 
     return stub; 
    } 
    return data.Find(f => f.id == targetId); 
} 

Я хочу что-то вроде

... 
public static Item Get(int targetId) 
{ 
    Item result; 
    result = data.Find(f => f.id == targetId); 
    if (result == null) 
    { 
     return stub; 
    } 
    return result; 
} 
+6

Это немного неясно, что именно вы просите, но кажется, что вы ищете 'FirstOrDefault()' я думаю. – CodeCaster

+0

@CodeCaster Однако, если данные не уникальны, он может вернуть неверный. – Greg

+0

Редактировать код, чтобы показать, что такое 'data'. Basic Find возвращает null, если ничего не может найти? –

ответ

0

Так FirstOrDefault() это путь. Вы также можете использовать SingleOrDefault(), если в этом списке должен быть только один элемент.

static stub = new Item() { text = "NaN", id = -1 }; 
    public static Item get(int i) 
    { 
     Item result; 
     result = data.FirstOrDefault(f => f.id == i); 

     if (result == null) 
     { 
      return stub; 
     } 

     return result; 
    } 
3

Вы, кажется, ищет FirstOrDefault():

Item _stub = new Item 
{ 
    text = "NaN", 
    id = -1 
}; 

public Item FindByID(int id) 
{ 
    // Find the first item that has the provided id, or null if none exist. 
    var existingItem = data.FirstOrDefault(i => i.id == id); 

    // When not found, return the _stub 
    return existingItem ?? _stub; 
} 

Вы также можете пересмотреть свои соглашения об именах и если вы на самом деле нужны эти элементы, чтобы быть static.

+0

Спасибо, это хорошо. Static is Ok ('sub' и' data' является объектом глобального чтения для этого класса). Не могу понять, что не так с именами. –

+0

@Stepan читает [MSDN: принципы именования] (https://msdn.microsoft.com/en-us/library/xzf533w0 (v = vs.71) .aspx) и особенно [MSDN: стили капитализации] (https://msdn.microsoft.com/en-us/library/x2dbyw72(v=vs.71).aspx). Публичные методы должны быть в общем случае 'PascalCased'. Также имя метода 'get' и его параметр с именем' i' на самом деле не являются описательными. – CodeCaster

2

Вы можете использовать List.FindIndex:

public static Item get(int i) 
{ 
    int index = data.FindIndex(item => item.id == i); 
    if (index == -1) return stub; 
    return data[index]; 
} 

Если это на самом деле массив можно использовать Array.FindIndex:

public static Item get(int i) 
{ 
    int index = Array.FindIndex(data, item => item.id == i); 
    if (index == -1) return stub; 
    return data[index]; 
} 
+0

FindIndex() тоже хорошо. Не могу понять, как я пропустил этот метод. –

0

Я думаю, вы можете попробовать это:

return data.Find(f => f.id == i) ?? stub; 
+1

Обновленный пример. –

0

Я использую метод расширения для этой цели

public static T FirstOrSpecificDefault<T>(this IEnumerable<T> list, 
             Func<T, bool> predicate, T defaultValue) 
{ 
    return list.FirstOrDefault(predicate) ?? defaultValue; 
} 

использования в вашем случае будет

Item result = list.FirstOrSpecificDefault(f => f.id == i, stub); 
Смежные вопросы