Переименовать со случайными числами - PullRequest
0 голосов
/ 27 февраля 2020

Я пытался сделать что-то подобное ... По сути, я пытаюсь перетасовать Муси c по их именам. Все работает хорошо, но мне было интересно, есть ли способ, чтобы случайная функция не повторяла одинаковые числа?

private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
     button1.Enabled = true;

     DirectoryInfo dir = new DirectoryInfo(comboBox1.SelectedItem.ToString());
     count = dir.GetFiles().Length;
     label3.Text = "Files loaded: " + count.ToString();
}
private void button1_Click(object sender, EventArgs e)
{

     DirectoryInfo d = new DirectoryInfo(comboBox1.SelectedItem.ToString());
     FileInfo[] infos = d.GetFiles("*.mp3");
     int i = 1;

     foreach (FileInfo f in infos)
     {
         File.Move(f.FullName, Path.Combine(f.DirectoryName, i + ". " + f.Name));
         i = rnd.Next(1, count+1);
     }
}

Ответы [ 3 ]

1 голос
/ 27 февраля 2020

Вы можете попробовать что-то вроде этого:

string path = comboBox1.SelectedItem.ToString();

var files = Directory.GetFiles(path, "*.mp3");
// Create list of shuffled numbers
var shuffledNumbers = Enumerable.Range(1, files.Length).ToArray().OrderBy(i => Guid.NewGuid());
// put the shuffled numbers into a stack
var indexes = new Stack<int>(shuffledNumbers);
foreach(var file in files) {
    // extract first item from the stack
    var index = indexes.Pop();
    // move file
    File.Move(file, Path.Combine(path, $"{index}. {Path.GetFileName(file)}"));
}

По сути, я тасую массив последовательных чисел, используя Guid.NewGuid в качестве ключа заказа.

Каждый раз, когда OrderBy сравнивает два элементы массива, он получит другое, совершенно случайное значение.

Использование стека позволяет мне просто вытолкнуть следующее число без необходимости использовать переменную индексатора (но это вполне нормально, если вы предпочитаете этот способ) .

0 голосов
/ 27 февраля 2020

Я согласен с ответом Макса. Если кто-то найдет это полезным, у меня есть пакет Nuget с именем RandomShuffler:

DataJuggler.RandomShuffler.Core (Dot Net Core)

DataJuggler.Core.RandomShuffler (. Net Framework)

Разница между Shuffler и Генератором случайных чисел заключается в том, что shuffler тянет все время, как колоду карт, и приводит к более равномерному распределению, где случайные числа могут выравниваться в течение нескольких миллионов лет или более.

enter image description here

Получите минимальные и максимальные границы вашего списка или массива

using DataJuggler.RandomShuffler.Core;

int min = 0;
int max = List.Count -1;

// Create a new instance of a 'RandomShuffler' object.
Shuffler = new RandomShuffler(min, max, 1, 3);

Это создаст список между вашими минимальными и максимальными значениями и 1 как третий параметр означает только 1 набор (без дубликатов).

Тогда каждый раз, когда вам нужно новое значение, просто вызывайте Shuffler.PullNextItem:

// pull the next White value
int index = Shuffler.PullNextItem();

var songToPlay = List[index]; // not sure what properties you need

Это автоматически перемешивает если у вас закончились, а также есть переопределения для карт.

Полный исходный код включен сюда, наряду с 30 другими бесплатными проектами:

https://github.com/DataJuggler?tab=repositories

0 голосов
/ 27 февраля 2020

Простой способ сделать это - создать список ваших файлов, в который вы поместите все имена. Затем вы перетасовываете этот список, используя что-то вроде Fisher-Yates shuffle , что дает вам гарантированную случайную последовательность. Затем вы можете просто выполнить обычный for-l oop над списком и переименовать файлы в соответствии с вашей переменной подсчета.

Таким образом, вместо того, чтобы создавать случайные числа для переименования объектов, вы просто перетасовываете их как колода карт и переименовать их на основе нового порядка. Кроме того, обратите внимание, что случайным образом Фишера-Йейтса является O (n), поскольку для рандомизации любого набора значений требуется только одно выполнение.

Пример кода на основе вашего кода:

DirectoryInfo d = new DirectoryInfo(comboBox1.SelectedItem.ToString());
List<FileInfo> infos = new List<FileInfo>(d.GetFiles("*.mp3"));

infos.FisherYatesShuffle(rnd);

for (int i = 0; i < files.Count; ++i)
{
    File.Move(f.FullName, Path.Combine(f.DirectoryName, i + ". " + f.Name));
}

И некоторый (непроверенный) алгоритм Фишера-Йейтса-Шаффла, который я только что взломал вместе как метод расширения для списков:

public static void FisherYatesShuffle<T>(this IList<T> list, Random random)
{
    for (int i = 0; i < list.Count; i++)
    {
        int index = rnd.Next(0, list.Count - i);
        int lastIndex = list.Count - i - 1;
        T value = list[index];
        {
            T temp = list[num1];
            list[num1] = list[num2];
            list[num2] = temp;
        }
        list.RemoveAt(lastIndex);
        list.Add(value);
    }
}
...