@mr_blond97

C# Как получить элементы из List используя Linq и Dictionary Class в запросе?

Модель:
public class Word
{
    public Dictionary<string, string> Langs { get; set; }
}


Список языков которые нужно использовать:
// I need to use these 2 langs only
    List<string> langsToUse = new List<string> { "en", "pl" };


Список слов содержит языки которые не нужно выбирать, а так содержит "" в значениях локализаций.
List<Word> wordsList = new List<Word> {
new Word {
    Langs = new Dictionary<string, string> {
        {"en", "Dog"},
        {"pl", "Pies"},
        {"ge", "Hund"},
        //... and so on
    }},
new Word {
    Langs = new Dictionary<string, string> {
        {"en", "Kat"},
        {"pl", ""},
        {"ge", ""}
        //... and so on
    }},
new Word {
    Langs = new Dictionary<string, string> {
        {"en", "Car"},
        {"pl", ""},
        {"ge", ""}
        //... and so on
    }},
};


Простой путь валидации:
// And value shouldn't be ""
var validWords = wordsList.Where(p => p.Langs["en"] != "" &&
                                      p.Langs["pl"] != "");


Но я не хочу каждый раз вручную прописывать "en", "pl", нужно это автомитизировать, например так:
// use foreach for validate words
List<Word> validWords_2 = new List<Word>();

foreach(Word word in wordsList)
{
    bool isWordValid = true;

    foreach(string lang in langsToUse)
    {
        if(word.Langs[lang] == ""){
            isWordValid = false;
        }
    }

    if(isWordValid) {
        validWords_2.Add(word);
    }
}


Как упростить этот вариант оптимизации и можно ли сделать это с использованием Dictionary в Linq запросе?
  • Вопрос задан
  • 4166 просмотров
Решения вопроса 1
В компиляторе не проверил, но должно работать. То, что вам нужно на последней строке.

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        public class Word
        {
            public Dictionary<string, string> Langs;
        }

        static void Main(string[] args)
        {
            List<string> langsToUse = new List<string> { "en", "pl" };

            List<Word> wordsList = new List<Word> {
                new Word {
                    Langs = new Dictionary<string, string> {
                        {"en", "Dog"},
                        {"pl", "Pies"},
                        {"ge", "Hund"},
                        //... and so on
                    }},
                new Word {
                    Langs = new Dictionary<string, string> {
                        {"en", "Kat"},
                        {"pl", ""},
                        {"ge", ""}
                        //... and so on
                    }},
                new Word {
                    Langs = new Dictionary<string, string> {
                        {"en", "Car"},
                        {"pl", ""},
                        {"ge", ""}
                        //... and so on
                    }},
            };

            // select all words with condition
            List<Word> validWords_2 = wordsList.Where(w => langsToUse.All(l => w.Langs[l] != "")).ToList();
        }
    }
}
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@ColdSpirit
Код:
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        public class Word
        {
            public Dictionary<string, string> Langs;
        }

        static void Main(string[] args)
        {
            List<string> langsToUse = new List<string> { "en", "pl" };

            List<Word> wordsList = new List<Word> {
                new Word {
                    Langs = new Dictionary<string, string> {
                        {"en", "Dog"},
                        {"pl", "Pies"},
                        {"ge", "Hund"},
                        //... and so on
                    }},
                new Word {
                    Langs = new Dictionary<string, string> {
                        {"en", "Kat"},
                        {"pl", ""},
                        {"ge", ""}
                        //... and so on
                    }},
                new Word {
                    Langs = new Dictionary<string, string> {
                        {"en", "Car"},
                        {"pl", ""},
                        {"ge", ""}
                        //... and so on
                    }},
            };

            // LETS START

            // select all words with condition
            var words = wordsList.Where(w => true);

            foreach (var word in words)
            {
                // select langs where langsToUse contains it
                var langs = word.Langs.Where(l => langsToUse.Contains(l.Key));
                // show in console
                Console.WriteLine("Langs in langsToUse:");
                langs.ToList().ForEach(l => Console.WriteLine("{0} -> {1}", l.Key, l.Value));

                // is all values in selection are not epty?
                bool isValid = langs.All(l => l.Value != "");
                // show in console
                Console.WriteLine("All not Empty, method one: {0}", isValid);

                // OR another method
                // is any value contains empty string?
                bool containsEmptyStr = langs.Any(l => l.Value == "");
                isValid = !containsEmptyStr;
                Console.WriteLine("All not Empty, method two: {0}", isValid);

                // add some formatting
                Console.WriteLine("\n");
            }

            // COMBINE

            var selected = wordsList.Where(
                word => word.Langs
                    .Where(lang => langsToUse.Contains(lang.Key))
                    .All(l => l.Value != ""));

            // show in console:
            Console.WriteLine("Combined method:");
            selected.ToList()
                .ForEach(w => w.Langs.ToList()
                    .ForEach(l => Console.WriteLine("{0} -> {1}", l.Key, l.Value)));

            Console.ReadKey();
        }
    }
}


Вывод:
Langs in langsToUse:
en -> Dog
pl -> Pies
All not Empty, method one: True
All not Empty, method two: True


Langs in langsToUse:
en -> Kat
pl ->
All not Empty, method one: False
All not Empty, method two: False


Langs in langsToUse:
en -> Car
pl ->
All not Empty, method one: False
All not Empty, method two: False


Combined method:
en -> Dog
pl -> Pies
ge -> Hund


Это конечно всё интересно, но код нечитаемый получается. Используйте лучше обычные циклы или раздельный вариант запросов.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы