Я хочу знать цепочку в случайном порядке
Пример строка
string word;
//I want to shuffle it
word = "hello"
Я мог бы получить:
rand == "ohlel"
rand == "lleho"
etc.
Я хочу знать цепочку в случайном порядке
Пример строка
string word;
//I want to shuffle it
word = "hello"
Я мог бы получить:
rand == "ohlel"
rand == "lleho"
etc.
Это решение (в форме метода расширения) приятно:
public static string Shuffle(this string str)
{
char[] array = str.ToCharArray();
Random rng = new Random();
int n = array.Length;
while (n > 1)
{
n--;
int k = rng.Next(n + 1);
var value = array[k];
array[k] = array[n];
array[n] = value;
}
return new string(array);
}
Вы ищете что-то вроде Fisher-Yates shuffle. На самом деле есть пример Python на этой странице:
import random
def shuffle(x):
for i in reversed(range(1, len(x))):
# pick an element in x[:i+1] with which to exchange x[i]
j = random.randrange(i+1)
x[i], x[j] = x[j], x[i]
Изменить. Поскольку ваш вопрос отмечен как ironpython
, так и c#
, там также есть пример Java, который очень легко конвертируется в С#.
С#:
string str = "hello";
// The random number sequence
Random num = new Random();
// Create new string from the reordered char array
string rand = new string(str.ToCharArray().
OrderBy(s => (num.Next(2) % 2) == 0).ToArray());
Попробуйте Fisher-Yates Shuffle:
class Shuffle
{
static System.Random rnd = new System.Random();
static void Fisher_Yates(int[] array)
{
int arraysize = array.Length;
int random;
int temp;
for (int i = 0; i < arraysize; i++)
{
random = i + (int)(rnd.NextDouble() * (arraysize - i));
temp = array[random];
array[random] = array[i];
array[i] = temp;
}
}
public static string StringMixer(string s)
{
string output = "";
int arraysize = s.Length;
int[] randomArray = new int[arraysize];
for (int i = 0; i < arraysize; i++)
{
randomArray[i] = i;
}
Fisher_Yates(randomArray);
for (int i = 0; i < arraysize; i++)
{
output += s[randomArray[i]];
}
return output;
}
}
class Program
{
static void Main()
{
string original = "Hello World!";
string mixedOriginal = Shuffle.StringMixer(original);
System.Console.WriteLine("The original string: {0}", original);
System.Console.WriteLine("A mix of characters from the original string: {0}", mixedOriginal);
System.Console.ReadKey();
}
}
вдохновлен порядком tsql 'by newid()
static string shuffle(string input)
{
var q = from c in input.ToCharArray()
orderby Guid.NewGuid()
select c;
string s = string.Empty;
foreach (var r in q)
s += r;
return s;
}
Лучший способ перетасовать строку или список строк используется таким образом. Здесь вы не получите дубликатов:
class CardsDeck
{
public static Random r = new Random();
private static List<string> cards = new List<string>{ "♣ King", "♣ Queen", "♣ Jack", " ♣", "♣ 7", "♣ 8", "♣ 9", "♣ 10",
"♦ King", "♦ Queen", "♦ Jack", " ♦", "♦ 7", "♦ 8", "♦ 9", "♦ 10",
"♥ King", "♥ Queen", "♥ Jack", " ♥", "♥ 7", "♥ 8", "♥ 9", "♥ 10",
"♠ King", "♠ Queen", "♠ Jack", " ♠", "♠ 7", "♠ 8", "♠ 9", "♠ 10" };
public string ReceiveCards()
{
if (cards.Count > 0)
{
int index = r.Next(cards.Count);
var card = cards[index];
cards.RemoveAt(index);
return card;
}
else
{
return "";
}
}
}
class Program
{
static void Main(string[] args)
{
string word = "hello";
string temp = word;
string result = string.Empty;
Random rand = new Random();
for (int a = 0; a < word.Length; a++)
{
//multiplied by a number to get a better result, it was less likely for the last index to be picked
int temp1 = rand.Next(0, (temp.Length - 1) * 3);
result += temp[temp1 % temp.Length];
temp = temp.Remove(temp1 % temp.Length, 1);
}
Console.WriteLine(result);
}
}
Вы можете попробовать что-то вроде этого.
class Program
{
static bool IsPositionfilled(int Position, List<int> WordPositions)
{
return WordPositions.Exists(a => a == Position);
}
public static string shufflestring(string word)
{
List<int> WordPositions = new List<int>();
Random r = new Random();
string shuffledstring = null;
foreach (char c in word)
{
while (true)
{
int position = r.Next(word.Length);
if (!IsPositionfilled(position, WordPositions))
{
shuffledstring += word[position];
WordPositions.Add(position);
break;
}
}
}
return shuffledstring;
}
static void Main(string[] args)
{
string word = "Hel";
Hashtable h = new Hashtable();
for (int count = 0; count < 1000; count++)
{
Thread.Sleep(1);
string shuffledstring = shufflestring(word);
if (h.Contains(shuffledstring))
h[shuffledstring] = ((int)h[shuffledstring]) + 1;
else
h.Add(shuffledstring,1);
}
Console.WriteLine(word);
foreach (DictionaryEntry e in h)
{
Console.WriteLine(e.Key.ToString() + " , " + e.Value.ToString());
}
}
}
Я выполняю это с помощью этого расширения:
public static class Extensions{
public static string Scramble(this string s){
return new string(s.ToCharArray().OrderBy(x=>Guid.NewGuid()).ToArray());
}
}
Следует помнить, что входная строка может содержать такие вещи, как суррогатные пары и диакритические знаки. Если это проблема, вы можете попробовать перетасовать элементы текста:
using System;
using System.Globalization;
using System.Linq;
using System.Text;
public static class StringExtensions
{
public static string ShuffleByTextElements(this string source, Random random)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (random == null) throw new ArgumentNullException(nameof(random));
var info = new StringInfo(source);
var indices = Enumerable.Range(0, info.LengthInTextElements).ToArray();
// Fisher-Yates shuffle
for (var i = indices.Length; i-- > 1;)
{
var j = random.Next(i + 1);
if (i != j)
{
var temp = indices[i];
indices[i] = indices[j];
indices[j] = temp;
}
}
var builder = new StringBuilder(source.Length);
foreach (var index in indices)
{
builder.Append(info.SubstringByTextElements(index, 1));
}
return builder.ToString();
}
}
Обратите внимание, что приведенный выше код по-прежнему не будет правильно обрабатывать некоторые функции Unicode, такие как двунаправленные переопределения, и не будет обрабатывать детали определенных сценариев, где форма буквы зависит от того, где она находится в слове. Примером этого может быть греческая строчная сигма, которая кодируется как греческая малая буква U + 03C3 (σ), за исключением конца слова, в котором вместо греческой буквы U + 03C2 используется финальная сигма (ς).
Я пробовал использовать старую школу, это хорошо работает.
static void Main()
{
string input = "hello";
string output = "";
int ranIndex = 0;
List<int> indexes = new List<int>();
char[] split = input.ToCharArray();
Random ran = new Random();
for (int i = 0; i < input.Length; i++)
{
ranIndex = ran.Next(0, input.Length);
if (!indexes.Contains(ranIndex))
{
indexes.Add(ranIndex);
}
else
{
i--;
}
}
foreach (int value in indexes)
{
output += split[value];
}
Console.WriteLine(output);
Console.ReadLine();
}
Фишера-Йейтс
static Random rand = new Random();
public static string ShuffleString(string s)
{
if (string.IsNullOrEmpty(s))
return s;
char[] chars = s.ToCharArray();
char c;
int j;
for(int i = chars.Length - 1; i > 0; i--)
{
j = rand.Next(i + 1); // Next max is exclusive
if (j == i)
continue;
c = chars[j];
chars[j] = chars[i];
chars[i] = c;
}
return chars.ToString();
}