2016-12-03 3 views
-2

У меня есть список, который содержит элементы, как это:список Restructure элементы в группы

{ 
Answer: "test answer", 
FaqTopicName :"General", 
Question: "test question", 
SortOrder: 0 
}, 

{ 
Answer: "...", 
FaqTopicName :"General", 
Question: "...", 
SortOrder: 1 
}, 

... (repeated) 

Я желаю, чтобы перестроить список, так что он теперь содержит каждый элемент списка сгруппированных внутри объекта. Объект результата будет выглядеть следующим образом и будет содержать все элементы, которые имеют одно и то же имя FaqTopicName под названием «items» = [].

Формат данных Я хочу, чтобы в конечном итоге с:

{ 
    topicName: "General", 
    items: { 
     Answer: "test answer", 
     Question: "test question", 
     SortOrder: 0 
     }, 
     { 
     Answer: "...", 
     Question: "...", 
     SortOrder: 1 
     } 
} 

Вот то, что я пытался, но он не выходит правильно, а также не будет проходить через JavaScriptSerializer():

List<FaqQuestionAnswer> allFaqItemsInSelectedSytem = faqController.GetAllFaqItemsForSystem(out errors); 

var groupedData = (from qaItem in allFaqItemsInSelectedSytem 
        group qaItem by qaItem.FaqTopicName 
        into questionsAnswersGroupedDataset 
          select questionsAnswersGroupedDataset).Distinct().ToDictionary(items => new { title = items.Key.ToString(), items = items.ToList() }); 

в результате в этом в отладчик:

[0] = {[{название = электронные книги, товар = System.Collections.Generic.List 1[JPay.Base.FaqQuestionAnswer] }, System.Linq.Lookup 2 + Группировка [System.String, JPay.Base.FaqQuesti onAnswer]]}

, но когда я запускаю его через конвертер JSON он выдает ошибки типа:

Тип «System.Collections.Generic.Dictionary 2[[<>f__AnonymousType0 2 [[System.String, mscorlib, Version = 4.0.0.0 , Culture = neutral, PublicKeyToken = XXXXXXXXXXX], [System.Collections.Generic.List 1[[Base.FaqQuestionAnswer, Version=1.0.6180.30742, Culture=neutral, PublicKeyToken=null]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=XXXXXXXXXXXX]], tttwebsite, Version=1.0.6181.25360, Culture=neutral, PublicKeyToken=null],[System.Linq.IGrouping 2 [[System.String, mscorlib, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = XXXXXXXXXXXXX], [ttt.Base.FaqQuestionAnswer, tttBase, Version = 1.0.6180.30742, Culture = neutral, PublicKeyToken = null]], System.Core, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = XXXXXXXXXXXXXXXXX]] 'не поддерживается для сериализации/десериализации словаря, ключей должны быть строками или объектами.

Спасибо за помощь.

+0

Когда вы говорите «это не получается правильно», какой формат данных вы получаете вместо этого? –

ответ

0

Основной вопрос здесь:

.ToDictionary(items => new { title = items.Key.ToString(), items = items.ToList() }); 

Вы, наверное, думаете, что вы определяете словарь с Key = items.Key.ToString() и Value = items.ToList(), но на самом деле ToDictionaryoverload вы использовали имеет следующую подпись:

public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(
    this IEnumerable<TSource> source, 
    Func<TSource, TKey> keySelector 
) 

поэтому вы преобразовываете результат в какой-то странный словарь с анонимным типом { string title, IEnumerable<FaqQuestionAnswer> items } в качестве ключа и IGrouping<string, IEnumerable<FaqQuestionAnswer>> в качестве значения.

Если вам действительно нужен словарь, то вы должны использовать вместо this overload:

public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(
    this IEnumerable<TSource> source, 
    Func<TSource, TKey> keySelector, 
    Func<TSource, TElement> elementSelector 
) 

так:

.ToDictionary(g => g.Key, g => g.ToList()); 

отметить также, что после того, как DistictGroupBy является излишним.

Чтобы получить точный формат вы описали, вы можете использовать простые GroupBy с пользовательскими Select:

var groupedData = allFaqItemsInSelectedSytem 
    .GroupBy(e => e.FaqTopicName) 
    .Select(g => new 
    { 
     topicName = g.Key, 
     items = g.Select(e => new { e.Answer, e.Question, e.SortOrder }).ToList() 
    }).ToList(); 

или, если вы предпочитаете синтаксис запроса:

var groupedData = 
    (from e in allFaqItemsInSelectedSytem 
    group e by e.FaqTopicName into g 
    select new 
    { 
     topicName = g.Key, 
     items = (from e in g select new { e.Answer, e.Question, e.SortOrder }).ToList() 
    }).ToList(); 
+0

Привет, спасибо за помощь. Я не могу получить этот результат для преобразования в JSON, похоже, все еще имеет такую ​​же проблему таким образом –

0

Я закончил с этим, что дало мне нужны были результаты:

protected string GetJPayWebsiteFaqTopics() 
    { 
     // call the FAQ manager 
     var faqController = managers.GetFaqManager(); 
     string errors = string.Empty; 
     string result = string.Empty; 

     // All items returned from faq manager, 2d collection not grouped into topic dictionaries 
     List<FaqQuestionAnswer> allFaqItemsInSelectedSystem = faqController.GetAllFaqItemsForSystem(out errors); 

     // Storage for main data, prior to serialization 
     List<Dictionary<string, object>> allFaqTopicsAndItems = new List<Dictionary<string, object>>(); 

     // Group all item Lists together in alike topic related faq items 
     IEnumerable<IGrouping<string, FaqQuestionAnswer>> groupedData = from qaItem in allFaqItemsInSelectedSystem 
                     group qaItem by qaItem.FaqTopicName; 
     // Allow the groupData to get iterated 
     IGrouping<string, FaqQuestionAnswer>[] enumerableGroups = groupedData as IGrouping<string, FaqQuestionAnswer>[] ?? groupedData.ToArray(); 
     JavaScriptSerializer jsonConverter = new JavaScriptSerializer(); 

     foreach (var instance in enumerableGroups) 
     { 
      // Each group of data should have a title for the group, a list of FAQ items 
      var items = instance.ToList(); 

      // Temp storage for each topic and associated faq item data 
      Dictionary<string, object> group = new Dictionary<string, object>(); 

      /** 
      * Temp storage for clean faq items stripped of topic level data which has now 
      * been added to the parent node so no longer needed at this level 
      */ 
      List<QuestionAnswerOrderOnly> cleanedItems = new List<QuestionAnswerOrderOnly>(); 

      // Add the group title 
      group.Add("Title", instance.Key); 

      // Add the topics display order to the group data 1st item since it is on every item 
      group.Add("TopicOrder", items[0].TopicOrder); 

      /** 
      * Pull the values that are important for the item only, add it to the group 
      * Clean up item before recording it to the group it belongs to 
      */ 
      cleanedItems.AddRange(items.Select(item => new QuestionAnswerOrderOnly(item.Question, item.Answer, item.ItemOrder))); 

      // Add the clean faqitems collection 
      group.Add("Items", cleanedItems); 

      // Add this topic group to the result 
      allFaqTopicsAndItems.Add(group); 
     } 

     jsonConverter.MaxJsonLength = Int32.MaxValue; 

     try 
     { 
      result = jsonConverter.Serialize(allFaqTopicsAndItems); 
     } 
     catch (Exception error) 
     { 
      result = $"{errors} {error.Message}"; 
     } 

     return result; 
    } 

и вывести следующие:

{ 
    topicName: "General", 
    items: { 
     Answer: "test answer", 
     Question: "test question", 
     SortOrder: 0 
     }, 
     { 
     Answer: "...", 
     Question: "...", 
     SortOrder: 1 
     } 
} 

Я надеюсь, что это поможет кому-то другому, находящемуся в подобной ситуации.

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