Упорядочивание списка‹String› по совпадающему значению имени Enum

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

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

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

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

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

    public enum ProcessWorkFlowOrder 
    {    
       File1,
       File3,
       File2           
    }

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

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


person proggrock    schedule 24.05.2011    source источник


Ответы (3)


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

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

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

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

person Anthony Pegram    schedule 24.05.2011
comment
Я согласен с Энтони. Enum.ToString() кажется хорошим, если вы не запутываете свой код. После запутывания любой код, использующий Enum.ToString(), перестанет работать. - person Brian Dishaw; 24.05.2011
comment
Брайан: (1) Не всем нужно запутывать, и (2) когда вы запутываете, вы можете не запутывать определенные поля перечисления. - person configurator; 24.05.2011
comment
Конечно, все это правда. Я хотел указать на ошибку с использованием Enum.ToString() и обфускации. Тем более, что он не уточнил, запутан код или нет. - person Brian Dishaw; 24.05.2011
comment
не запутан, но спасибо за комментарии, и Энтони, мне нравится ваш ответ, только что попробовал, и он отлично работает. Если у кого-нибудь есть способ сделать это через имя Enum, было бы здорово увидеть? - person proggrock; 24.05.2011
comment
@ProgRockCode Я думаю, что мой ответ соответствует исходному брифу, или я ошибаюсь? - person Jodrell; 24.05.2011

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

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;
person configurator    schedule 24.05.2011
comment
Выглядит многообещающе, но я получаю «System.Array не содержит определения для Select». - person proggrock; 24.05.2011
comment
Это использует Linq; добавьте using System.Linq; в начало файла. - person configurator; 25.05.2011
comment
если добавление с использованием System.Linq не помогает, попробуйте выполнить приведение таким образом: Enum.GetValues(typeof(ProcessWorkFlowOrder)).Cast<ProcessWorkFlowOrder>().Select(... - person danyolgiax; 09.01.2013
comment
@danyolgiax: В этом нет необходимости - вы можете видеть, что лямбда отлично работает, когда принимает Object - она ​​выполняет приведение при получении значения. - person configurator; 09.01.2013
comment
очень странно! Без этого приведения мой код не скомпилируется! System.Array does not contain a definition for Select... ошибка! - person danyolgiax; 10.01.2013
comment
@danyolgiax: Подумав еще немного, вы правы. IEnumerable не расширяется System.Linq, за исключением включения Cast и OfType. Я ошибочно принял его за IEnumerable<object>. Извините, я немного заржавел - уже довольно давно не прикасался к C#. - person configurator; 10.01.2013
comment
Теперь я отредактировал свой код, чтобы он был правильным, и OfType убедился, что перечисление введено правильно. - person configurator; 10.01.2013

как насчет?

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 result;
    });

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

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