Упорядочивание списка по значению имени соответствующего перечисления

#c# #linq #list #enums #matching

#c# #linq #Список #перечисления #сопоставление

Вопрос:

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

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

Допустим, у меня есть полный список строк:

     List<string> filenames = new List<string>();
  

И у меня есть связанное перечисление для отображения файлов в определенном порядке:

     public enum ProcessWorkFlowOrder 
    {    
       File1,
       File3,
       File2           
    }
  

Строковое значение «filenames» в списке будет точно соответствовать имени перечисления.

Каков наилучший способ сопоставления и упорядочивания списка имен файлов по совпадающему значению перечисления?

Ответ №1:

Если имена файлов точно совпадают, я бы использовал не перечисление, а другой список, сохраняющий порядок.

 List<string> namesInOrder = ...
List<string> files = ...

var orderedFiles = from name in namesInOrder
                   join file in files 
                   on name equals file
                   select file;
  

Join сохраняет порядок первой последовательности и, следовательно, позволит вам использовать его для упорядочивания второй.

Комментарии:

1. Я согласен с Энтони. Перечисление. toString () кажется приятным, пока вы не запутываете свой код. После обфускации любой код, который использовал перечисление. toString() перестанет функционировать.

2. Брайан: (1) Не всем нужно выполнять обфускацию, и (2) при обфускации вы можете выбрать не обфускировать поля конкретного перечисления.

3. Конечно, все это правда. Я хотел указать на ошибку с использованием Enum. toString() и запутывание. Особенно потому, что он не указал, был ли код запутан или нет.

4. не запутано, но спасибо за комментарии, и Энтони, мне нравится твой ответ, просто попробовал, и он отлично работает. Если у кого-нибудь есть способ сделать это через имя перечисления, было бы здорово посмотреть?

5. @ProgRockCode Я думаю, что мой ответ соответствует исходному резюме, или я ошибаюсь?

Ответ №2:

Если у вас уже есть перечисление, и вы не можете изменить его на список строк, как предлагает Энтони, вы можете использовать это:

 var order = Enum.GetValues(typeof(ProcessWorkFlowOrder))
                .OfType<ProcessWorkFlowOrder>()
                .Select(x => new {
                                   name = x.ToString(),
                                   value = (int)x
                        });

var orderedFiles = from o in order
                   join f in filenames
                   on o.name equals f
                   orderby o.value
                   select f;
  

Комментарии:

1. Выглядит многообещающе, но я получаю ‘System. Массив не содержит определения для выбора’

2. При этом используется Linq; добавьте using System.Linq; в начало файла.

3. если добавление с помощью System.Linq не помогает, попробуйте выполнить приведение таким образом: Enum.GetValues(typeof(ProcessWorkFlowOrder)).Cast<ProcessWorkFlowOrder>().Select(...

4. @danyolgiax: В этом нет необходимости — вы можете видеть, что лямбда-выражение отлично работает, когда оно принимает Object — оно выполняет приведение при получении значения.

5. Теперь я отредактировал свой код, чтобы он был корректным, OfType убедившись, что перечисление введено правильно.

Ответ №3:

как насчет?

 var orderedFilenames = filenames.OrderBy(
    f => (int)Enum.Parse(typeof(ProcessWorkFlowOrder), f));
  

Однако я не уверен, что сохранение этого перечисления является наилучшим подходом, лучше написать функцию для определения алгоритма упорядочивания, что, если перечисление не содержит имени файла.

РЕДАКТИРОВАТЬ с помощью TryParse

 var orderedFilenames = filenames.OrderBy(f => {
       ProcessWorkFlowOrder parsed;
       int result = 0;
       if (Enum.TryParse<ProcessWorkFlowOrder>(f, out parsed))
           result = (int)parsed;
       return resu<
    });
  

Какие правила вы бы использовали для построения перечисления или списка с сохранением порядка, или порядок является чисто произвольным?

Комментарии:

1. Если какой-либо файл не будет иметь допустимого значения enum, это приведет к сбою и записи; поскольку в enum нет TryParse, вы не сможете легко отфильтровать их без дополнительного шага: Select(f => Enum.IsDefined(typeof(ProcessWorkFlowOrder), f))

2. @configurator, полностью согласен, но, по сути, это проблема с использованием перечисления для определения порядка. Однако доступен синтаксический анализ.