首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从数组中获取随机值

从数组中获取随机值
EN

Stack Overflow用户
提问于 2016-06-19 10:44:41
回答 3查看 157关注 0票数 0

我试图通过更改索引来随机更改数组的元素。没关系。现在的问题是,由于随机总是随机的,我可以得到两个相同的结果。

例如: 星期一: 歌1 歌2 歌3 星期二: 歌2 歌1 歌3 星期三: 歌1 歌2 歌3

等等..。

和名单

星期一

星期三

在这种情况下是一样的。我需要控制它,但是正如您在代码中所看到的,一旦我从一天中得到列表,我就会打印出来。我想把它放在一个数组或元组上,并检查这个元组是否存在,但我认为太复杂了。我想也许我可以做我自己的随机函数。不过,我也不确定这个解决方案。我有什么办法解决这个问题吗?谢谢!

下面是我到目前为止掌握的代码:

代码语言:javascript
复制
    static string[] songs = new string[] { "song1", "song2", "song3" };
    static string[] days = new string[] { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };
    private static Random random = new Random();

/* Random number between lower and higher, inclusive */
    public static int rand(int lower, int higher)
    {
        int r = lower + (int)(random.Next(0, 2) * (higher - lower));

        return r;
    }

    /* pick M elements from original array. Clone original array so that
   7 * we don’t destroy the input. */
    public static string[] pickMRandomly()
    {
        string[] subset = new string[songs.Length];
        string[] array = (string[])songs.Clone();
        for (int j = 0; j < songs.Length; j++)
        {
            int index = rand(j, array.Length - 1);
            subset[j] = array[index];
            array[index] = array[j]; // array[j] is now “dead”
        }
        return subset;
    }

    public static void playListCreation()
    {
        for (int j = 0; j < days.Length; j++)
        {
            var result =pickMRandomly();
            System.Console.WriteLine(days[j]);
            foreach (var i in result)
            {
                System.Console.WriteLine(i + " ");
            }
            System.Console.WriteLine("/n");
        }
    }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-06-19 11:19:28

如果我对你的理解是正确的,你不只是想要每天的歌曲的随机排列,你要的是每天独特的(随机的)歌曲安排。

我唯一能保证这一点的方法就是找出所有可能的歌曲组合,并随机排序--然后每天从列表中挑选一个不同的组合。

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Linq;

namespace StackOverflowAnswer
{
    class Program
    {
        static string[] songs = new string[] { "song1", "song2", "song3" };
        static string[] days = new string[] { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };

        static void Main(string[] args)
        {
            var rnd = new Random();
            var allCombinationsInRandomOrder = GetCombinations(songs, songs.Length)
                .Select(combination => new { Combination = combination, Order = rnd.Next() })
                .OrderBy(entry => entry.Order)
                .Select(entry => entry.Combination);

            var dayIndex = 0;
            foreach (var combination in allCombinationsInRandomOrder)
            {
                var day = days[dayIndex];
                Console.WriteLine(day);
                Console.WriteLine(string.Join(", ", combination));

                dayIndex++;
                if (dayIndex >= days.Length)
                    break;
            }
            Console.ReadLine();
        }

        private static IEnumerable<IEnumerable<string>> GetCombinations(IEnumerable<string> songs, int numberOfSongsInGeneratedLists)
        {
            if (songs == null)
                throw new ArgumentNullException(nameof(songs));
            if (numberOfSongsInGeneratedLists <= 0)
                throw new ArgumentOutOfRangeException(nameof(numberOfSongsInGeneratedLists));
            if (numberOfSongsInGeneratedLists > songs.Count())
                throw new ArgumentOutOfRangeException("can't ask for more songs in the returned combinations that are provided", nameof(numberOfSongsInGeneratedLists));

            if (numberOfSongsInGeneratedLists == 1)
            {
                foreach (var song in songs)
                    yield return new[] { song };
                yield break;
            }

            foreach (var combinationWithOneSongTooFew in GetCombinations(songs, numberOfSongsInGeneratedLists - 1))
            {
                foreach (var song in songs.Where(song => !combinationWithOneSongTooFew.Contains(song)))
                    yield return combinationWithOneSongTooFew.Concat(new[] { song });
            }
        }
    }
}
票数 2
EN

Stack Overflow用户

发布于 2016-06-19 11:18:48

据我所知,您想要创建一个随机播放列表,如果这个播放列表是以前创建的,那么您希望生成另一个播放列表(直到它是唯一的)。您可以这样做的一种方法是向HashSet中添加某种类型的散列,并查看它以前是否已经生成。例如,

代码语言:javascript
复制
bool HashSet<int> playlistHashes = new HashSet<int>();
private bool CheckIfUnique(string[] playlist)
{
    //HashSet returns false if the hash already exists 
    //(i.e. playlist already likely to have been created)
    return playlistHashes.Add(string.Join("",playlist).GetHashCode());
}

然后,一旦生成了播放列表,就可以调用该方法,并查看它是否返回false。如果它返回false,则以前已经创建了播放列表顺序,因此您可以再次生成。使用上述技术意味着song1, song2, song3song3, song2, song1不同,因此顺序非常重要。

正如我对这个问题的评论中提到的,如果你用3首歌测试,每周只有6个不同的排列和7天,所以你会得到一个副本。

附带注意,GetHashCode可以抛出“假阳性”,但这取决于您确定它有多大的可能性,以及它的影响是否真的有任何意义,因为新的播放列表是生成的。好线程获得更多信息,here。如果GetHashCode在这里还不够的话,有很多哈希技术可以降低碰撞的几率。

票数 1
EN

Stack Overflow用户

发布于 2016-06-20 03:09:37

考虑到您手头有3 Songs,并且希望为一周中的每一天(7天)分配独特的组合。这是不可能的,因为你只能做六个独特的组合与这三个。所以肯定有一个重复的序列。如果将另一首歌曲(让它是24 )添加到这个集合中,您将得到"song4"唯一的歌曲序列。我已经包括了一个片段,帮助您获得这些独特的歌曲序列组合。

代码语言:javascript
复制
string[] songs = new string[] { "song1", "song2", "song3", "song4" };       
int numberOfSongs = songs.Count();
var collection = songs.Select(x => x.ToString()); ;
for (int i = 1; i < numberOfSongs; i++)
{
    collection = collection.SelectMany(x => songs, (x, y) => x + "," + y);                            
}
List<string> SongCollections = new List<string>();
SongCollections.AddRange(collection.Where(x => x.Split(',')
                                   .Distinct()
                                   .Count() == numberOfSongs)
                                   .ToList());

现在,SongCollections将包含24独特的4歌曲序列。(如果您选择3首歌曲,那么您将得到6独特的序列)。您可以从这些集合中随机选择序列,并根据您的意愿将其分配给天数。

现在,让我使用一个Dictionary<string, int> dayCollectionMap将一个集合映射到一天(注意:,这里我使用了一个4歌曲集合,因为对于7 days来说,3是不够的)。考虑下面的片段:

代码语言:javascript
复制
Dictionary<string, int> dayCollectionMap = new Dictionary<string, int>();
string[] days = new string[] { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };
Random randomCollection = new Random();
foreach (string day in days)
{
    int currentRandom = randomCollection.Next(0, SongCollections.Count());
    if (!dayCollectionMap.Any(x => x.Value == currentRandom))
    {
        dayCollectionMap.Add(day, currentRandom);
    }
    else
    {
        // The collection is already taken/ Add another random sequence
        while (true)
        {
            currentRandom = randomCollection.Next(0, SongCollections.Count());
            if (!dayCollectionMap.Any(x => x.Value == currentRandom))
            {
                dayCollectionMap.Add(day, currentRandom);
                break;
            }

        }
    }

}

以便您可以使用以下代码为Wednesday选择歌曲集合

代码语言:javascript
复制
  var songCollectionForWed = SongCollections[dayCollectionMap["Wednesday"]];
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37906373

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档