C # Как перебрать массив и найти массив с самой последней датой? - PullRequest
0 голосов
/ 31 августа 2018

Новый C # ученик здесь. Я просмотрел много вопросов, которые уже были размещены здесь; Извините, если я пропустил такой вопрос, который уже был задан.

Фон

Программа, которую я использую, создает файлы Excel, имена которых содержат дату, в которую они были созданы. Создаются тысячи файлов Excel, которые необходимо отсортировать. Моя миссия здесь состоит в том, чтобы извлечь информацию из этих имен файлов, чтобы я мог переместить файл в соответствующее место после подтверждения. Я работаю с программой, которая успешно находит все связанные файлы с определенной строкой. Я сохранил имена этих файлов в массиве.

Пример имени файла: IMPORTANT_NAME_LISTED (TEXT) [xx-xx-xx] [HH_MM] .xlsx

Что известно

Дата хранится в «[]» в формате месяц / день / год и соответствует 100% (это означает, что каждый файл будет иметь одинаковый формат, размер и местоположение даты).

Я пытался разработать решение, которое нацелено на "." до расширения файла и извлечения даты, но я изо всех сил.

Моя стратегия

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

//code that extracts file names exists above
//file names which interest me are stored within "fileNameArray"

//Determine if the array that collected file names contains values

if (fileNameArray.Length > 1)
{
    for (int k = 0; k <= fileNameArray.Length; k++)
        {
            //Extract date from "[xx-xx-xx] [HH-MM]"
            //Transform MM/DD/YY to YY/MM/DD and temporarily store
            //Compare each date value that exist within the string
            //Target the most recent file - find the array index
            //(Ex: 20180831 - today's date)
        }
}

Мои проблемы возникают из-за правильного анализа этих отдельных элементов массива при сохранении индекса массива.

Кто-нибудь из вас рекомендует метод для использования? LINQ? Array.FindAll функциональность?

Я очень ценю помощь.

-Крис

Редактировать: Дополнительная информация о моей ситуации ...

У меня есть каталог файлов Excel, который может превышать ~ 1-3k файлов. У меня есть программа, которая читает имена файлов всех файлов Excel. Большая часть тяжелой фильтрации / сортировки происходит перед кодом, который я имею выше, который я хочу реализовать.

Я пытался решить проблему, связанную с обработкой файлов с одинаковыми именами. Например:

У меня есть 4 файла с одинаковым частичным именем "DILITHIUM_CRYSTYAL_FUEL_TIME"

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

Мои файлы всегда будут отображать отметку времени слева от расширения файла в соответствии со 100% -ной последовательностью.

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

Ответы [ 5 ]

0 голосов
/ 11 сентября 2018

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

Вот фрагмент из моего кода, который прекрасно решил мою проблему:

string scanToolDateFinalStgT1 = "";
DateTime scanToolDateFinalT1 = new DateTime(2000, 1, 1, 1, 1, 00);

for (int k = 0; k < scanToolT1Pass.Count(); k++)
{
    string scanToolPassNameOnly = Path.GetFileNameWithoutExtension(scanToolT1Pass[k].ToString());
    string scanToolDateStr = scanToolPassNameOnly.Substring(scanToolPassNameOnly.IndexOf("[") + 1, 8);
    string scanToolTimeStr = scanToolPassNameOnly.Substring(scanToolPassNameOnly.LastIndexOf("[") + 1, 5);
    DateTime currentScanToolDate = DateTime.ParseExact(scanToolDateStr + " " + scanToolTimeStr, "MM-dd-yy HH_mm", null);
    if (currentScanToolDate > scanToolDateFinalT1)
    {
        scanToolDateFinalT1 = currentScanToolDate;
        scanToolDateFinalStgT1 = scanToolT1Pass[k].ToString();
    }
}

Информация:

Этот фрагмент предназначен для таргетинга на '[xx-xx-xx] [xx-xx].', Который является частичным уникальным идентификатором имени файла.

Программа передает 'scanToolT1Pass', который является массивом имен файлов. Моя задача - взять этот массив и разобрать имена файлов, найдя самый последний.

«DateTime scanToolDateFinalT1» имеет общую дату 1/01/200, 1:01:00, которая строго используется в качестве базовой точки сравнения. Я уверен, что мои данные никогда не потребуют дат, которые произойдут до 2000 года. Я пытался использовать контрольную дату, считывающую все нули для сравнения, но VisualStudio не одобрил это.

Пояснение:

Существуют ли более продвинутые и / или правильные методы для анализа этих данных? Я уверен, что есть. Но для начинающего программиста этот метод имеет для меня много смысла, и я стремлюсь его усовершенствовать в будущем. Для меня было наиболее важно иметь программу, которая работает в первую очередь, чем вкладывать много усилий в ее совершенствование.

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

Еще раз спасибо сообществу и @Sach & @It Man, чьи ответы я смог найти в своем решении.

  • Chris
0 голосов
/ 01 сентября 2018

Вот решение без регулярных выражений.

var files = new List<string>
{
    "IMPORTANT_NAME_LISTED (TEXT) [05-26-92].xlsx",
    "IMPORTANT_NAME_LISTED (TEXT) [11-02-89].xlsx",
    "IMPORTANT_NAME_LISTED (TEXT) [02-21-96].xlsx"
};

foreach (var fileName in files)
{
    var nameOnly = Path.GetFileNameWithoutExtension(fileName);
    var dateStr = nameOnly.Substring(nameOnly.Length - 9, 8);
    if (DateTime.TryParseExact(dateStr, "MM-dd-yy", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime date))
        Console.WriteLine(date.ToShortDateString());
}

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

nameOnly.Substring(nameOnly.Length - 9, 8);

извлечет строку, начинающуюся сразу после первого [, и извлечет 8 символов, заканчивающихся до ].

И если вы на 100% уверены, что расширение файла всегда будет .xlsx, то вы можете сократить код еще больше.

foreach (var fileName in files)
{
    var dateStr = fileName.Substring(fileName.Length - 14, 8);
    if (DateTime.TryParseExact(dateStr, "MM-dd-yy", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime date))
        Console.WriteLine(date.ToShortDateString());    
}
0 голосов
/ 31 августа 2018

LINQ является хорошим выбором для этого в сочетании с Regex для разбора.

var dateRE = new Regex(@"\[(\d\d-\d\d-\d\d)\] \[(\d\d-\d\d)\](?=.xlsx)", RegexOptions.Compiled);

if (fileNameArray.Length > 0) {
    var ans = fileNameArray.Select((n, i) => {
                                var dtMatch = dateRE.Match(n);
                                return new { Filename = n, Index = i, Filedate = DateTime.ParseExact(dtMatch.Groups[1].Value+" "+dtMatch.Groups[2].Value, "MM-dd-yy HH-mm", CultureInfo.InvariantCulture) };
                            })
                           .OrderByDescending(nid => nid.Filedate)
                           .First();
}

Если вы хотите обрабатывать имена файлов по-другому, вы можете заменить First() другой операцией LINQ.

0 голосов
/ 01 сентября 2018

Я бы также использовал регулярные выражения, разбор строк и linq:

Рабочий пример здесь: https://dotnetfiddle.net/veUq2N

using System;
using System.Linq;
using System.Collections.Generic;
using System.Text.RegularExpressions;

public class Program
{
    private static Random random = new Random();
    private static Regex fileNameFragmentPattern = new Regex(@"\[(.*?)\]\.xlsx");
    private const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

    public static void Main()
    {
        var fileNames = new List<string>();

        // Generate random file names 
        for (var i = 0; i < 10000; i++) {
            fileNames.Add(RandomString(random.Next(8,10)) +  "_" + RandomString(random.Next(4,5)) + "_"  + "(TEXT) [" + RandomDate().ToString("MM-dd-yyyy") + "].xlsx");
        }

        // sort files by parsed dates
        var dateSortedFileNames = fileNames.OrderByDescending( f => ExtractDate(f));
        foreach (var fileName in dateSortedFileNames) {
            // you can do anything with sorted files here (or anywhere else below :)
            Console.WriteLine(fileName);
        }       
    }

    public static DateTime ExtractDate(string fileName) {
        var fragment = fileNameFragmentPattern.Match(fileName).Value;
        var month = int.Parse(fragment.Substring(1,2));
        var day = int.Parse(fragment.Substring(4,2));
        var year = int.Parse(fragment.Substring(7,4));
        return new DateTime(year, month, day);      
    }

    public static string RandomString(int length)
    {
        return new string(Enumerable.Repeat(chars, length)
          .Select(s => s[random.Next(s.Length)]).ToArray());
    }

    public static DateTime RandomDate(int min = -9999, int max = 9999)
    {
        return DateTime.Now.AddDays(random.Next(min,max));
    }
}
0 голосов
/ 31 августа 2018
public struct DatedExcelOutput
{
    public string FullName {  get; }
    public string Name { get; }
    public DateTime CreationDate { get; }

    public DatedExcelOutput(string fileName)
    {
        FullName = fileName;
        Name = getName();
        CreationDate = parseDate();
    }
}

Это можно назвать так:

IEnumerable<string> fileNames = GetFiles();
var datedFiles = fileNames.Select(f => new DatedExcelOutput(f))
                                  .OrderBy(d => d.CreationDate);

Вы, вероятно, в конечном итоге будете нуждаться в сортировке этих восходящих / нисходящих в пользовательском интерфейсе, верно? Поэтому я не думаю, что имеет смысл выбрасывать информацию о дате.

Редактировать: удалены ненужные вызовы ввода-вывода, как указано NetMage .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...