2016-08-24 2 views
0

У меня есть система, где люди могут прислать мне List<ProductCategory>.Сортировка списка по родительским/дочерним отношениям, поэтому я определенно обработал родителя, прежде чем пытаюсь обработать ребенка.

Мне нужно сделать некоторое сопоставление с моей системой, а затем сохранить их в базе данных.

входящие данные в этом формате:

public string ExternalCategoryID { get; set; } 
public string ExternalCategoryName { get; set; } 
public string ExternalCategoryParentID { get; set; } 

Входящий список в произвольном порядке. Если ExternalCategoryParentID имеет значение null, то это категория верхнего уровня. Родительские отношения с дочерними элементами могут быть любой глубиной - то есть технологией> телевизорами> Samsung> 3D> 40 "> и т. Д.> И т. Д.

Когда я спасаю, мне нужно убедиться, что я уже сохранил родителя - я не могу сэкономить Телевизоры до тех пор, пока я не сохраню технологию. ExternalCategoryID, скорее всего, будет int, но это не имеет отношения к родительским отношениям с дочерними элементами (родитель может иметь более высокий или более низкий идентификатор, чем ребенок).

Как заказать этот список поэтому я могу пройти через него и быть уверенным, что для любого ребенка я уже обработал его родитель.

Единственный способ, которым я могу думать, это получить все, где ExternalCategoryParentID == null, а затем получить все, где ExternalCategoryParentID находится в этом списке «Верхний уровень», затем получает следующий набор детей ... и т. Д., Но это не может быть лучшим решением. Я бы предпочел сначала отсортировать, а затем обработать один цикл. Я нашел сообщение this, но он полагается на createdDate, что не имеет отношения ко мне.

+1

Вы выполняете так называемую «топологическую сортировку на направленном ациклическом графе». Из введения к алгоритмам Томас Кормен: «... Еще один способ выполнить топологическую сортировку на направленном ациклическом графе - это многократно найти вершину степени 0, вывести ее и удалить ее и все ее исходящие ребра из графика «. Так или иначе, вы будете делать повторные звонки. –

ответ

1

Оказывается, это было не так трудно в конце концов. Я написал эту функцию, чтобы сделать это - вы переходите в исходный список и вернете отсортированный список.

Он работает, перебирая список, проверяя, есть ли какие-либо элементы в списке, которые имеют id == current items parentid. Если он есть, мы игнорируем этот элемент и продолжаем. если их нет, мы добавим текущий элемент в sortedList и удалим его из исходного списка и продолжим. Это гарантирует, что элементы будут вставлены в отсортированный список после их родителя.

private List<HeisenbergProdMarketplaceCategory> SortByParentChildRelationship(List<HeisenbergProdMarketplaceCategory> heisenbergMarketplaceCategories) 
{ 
    List<HeisenbergProdMarketplaceCategory> sortedList = new List<HeisenbergProdMarketplaceCategory>(); 

    //we can check that a category doesn't have a parent in the same list - if it does, leave it and continue 
    //eventually the list will be empty 
    while(heisenbergMarketplaceCategories.Count > 0) 
    { 
     for (int i = heisenbergMarketplaceCategories.Count-1; i >= 0; i--) 
     { 
      if (heisenbergMarketplaceCategories.SingleOrDefault(p => p.ExternalCategoryID == heisenbergMarketplaceCategories[i].ExternalCategoryParentID) == null) 
      { 
       sortedList.Add(heisenbergMarketplaceCategories[i]); 
       heisenbergMarketplaceCategories.RemoveAt(i); 
      } 
     } 
    } 

    return sortedList; 
} 
0

Мы можем проверить значение поля равным нулю, а затем установить для него int.max, а затем упорядочить по убыванию, чтобы получить его вверху.

Мы можем проверить ExternalCategoryID = field.Value ?? int.max, а затем Order by descending.

Пример:

var query = context.Categories.Select(o => new { Obj = o, OrderID = o.OrderID ?? int.MaxValue }).OrderByDescending(o => o.OrderID).Select(o => o.Obj); 
+0

Значение в ExternalCategoryParentID не имеет значения, поэтому я не могу его заказать. Совершенно очевидно, что у ребенка будет более низкий идентификатор, чем у его родителя. например «Телевизоры» уже существуют, затем мы добавляем новую категорию под названием «Tech», затем добавляем «TVs» к «Tech». Или обычная ситуация, когда родитель добавляется сначала, а потом ребенок. – Rick

+0

То, что я думал, это тот, который имеет категориюParentId как null, - это новые записи, а остальные записи, у которых categoryParentid уже есть категория tht в базе данных. – FakeisMe

Смежные вопросы