Trong C#, làm cách nào để nhận một số ngẫu nhiên từ một phạm vi giá trị - như 1..100, nhưng số đó không nằm trong một số danh sách giá trị cụ thể , như 5, 7, 17, 23?Cách lấy một số ngẫu nhiên từ một phạm vi, ngoại trừ một số giá trị
Trả lời
Kể từ khi không có ai đăng bài bất kỳ mã ví dụ:
private int GiveMeANumber()
{
var exclude = new HashSet<int>() { 5, 7, 17, 23 };
var range = Enumerable.Range(1, 100).Where(i => !exclude.Contains(i));
var rand = new System.Random();
int index = rand.Next(0, 100 - exclude.Count);
return range.ElementAt(index);
}
Đây là suy nghĩ:
- Xây dựng một Hashset số bạn muốn loại trừ
- Tạo một bộ sưu tập của tất cả các số 0-100 không có trong danh sách các số để loại trừ với một chút LINQ.
- Tạo một đối tượng ngẫu nhiên.
- Sử dụng đối tượng Ngẫu nhiên để cung cấp cho bạn một số từ 0 đến số yếu tố trong phạm vi số của bạn (bao gồm).
- Trả lại số tại chỉ mục đó.
Nếu bạn thực hiện 'exclude' một' HashSet' thay vì một 'List', và sử dụng' 100 - exclude.Count' thay vì 'range.Count()', điều này có thể hiệu quả hơn nữa :) – Rawling
@Rawling Điểm tuyệt vời - Tôi đã chỉnh sửa chúng. Tôi cũng nhận ra rằng OP muốn số từ 1 đến 100, không phải 0 và 100 như tôi đã đặt ban đầu. – Bridge
Tôi gặp lỗi trong dòng thứ 7: int index = rand.Next (0,100-exclude.Count); vì (.Next()), trong đó hệ thống chỉ thị tôi có thể tìm thấy điều này? lỗi mà tôi nhận được là lỗi CS1061: Loại 'UnityEngine.Random 'không chứa định nghĩa cho' Tiếp theo' và không có phương pháp mở rộng 'Tiếp theo 'loại' UnityEngine.Random' có thể được tìm thấy (bạn đang thiếu một chỉ thị sử dụng hoặc một tham khảo lắp ráp?) – tenthplanet0
Đặt số được phép vào một mảng, tạo số nguyên ngẫu nhiên từ 0 đến độ dài của mảng này trừ đi một. Sử dụng số nguyên này làm chỉ mục để lấy số ngẫu nhiên từ mảng số được cho phép.
Nếu mảng ban đầu chứa các đối tượng lớn thay vì số, thì tạo một mảng khác bằng cách sao chép sâu các đối tượng được phép sẽ không có hiệu lực. Trong trường hợp này, mảng các đối tượng được phép chỉ chứa một con trỏ, một tham chiếu hoặc một chỉ mục cho các đối tượng trong mảng ban đầu. Trong trường hợp này, bạn tạo một số nguyên ngẫu nhiên để chọn một phần tử của mảng này và sử dụng con trỏ/tham chiếu/chỉ mục này để lấy đối tượng đã chọn từ mảng gốc gốc.
Here là một ví dụ làm việc đối với trường hợp chung (chỉ là một giải pháp khả thi!):
using System;
using System.Collections.Generic;
public static class RandomElementSelector
{
public static IList<T> CollectAllowedElements<T>(IList<T> allElements, IList<T> excludedElements)
{
List<T> allowedElements = new List<T>();
foreach (T element in allElements)
if (!excludedElements.Contains(element))
allowedElements.Add(element);
return allowedElements;
}
public static T SelectRandomElement<T>(IList<T> allowedElements)
{
Random random = new Random();
int randomIndex = random.Next(allowedElements.Count);
return allowedElements[randomIndex];
}
public static T SelectRandomElement<T>(IList<T> allElements, IList<T> excludedElements)
{
IList<T> allowedElements = CollectAllowedElements(allElements, excludedElements);
return SelectRandomElement(allowedElements);
}
}
public class Test
{
public static void Main()
{
const int N = 100;
// Example #1
int[] allNumbers = new int[N];
for (int i = 0; i < allNumbers.Length; ++i)
allNumbers[i] = i + 1;
int[] excludedNumbers = { 5, 7, 17, 23 };
Console.WriteLine(RandomElementSelector.SelectRandomElement(allNumbers, excludedNumbers));
// Example #2
List<string> allStrings = new List<string>();
for (int i = 0; i < N; ++i)
allStrings.Add("Item #" + (i + 1));
string[] excludedStrings = { "Item #5", "Item #7", "Item #17", "Item #23" };
Console.WriteLine(RandomElementSelector.SelectRandomElement(allStrings, excludedStrings));
}
}
Cảm ơn bạn đã phản hồi. Bạn có thể cụ thể hơn không? Tôi có thể lấy mã cho điều này không? như mảng của tôi có thể phát triển lớn – tenthplanet0
@ tenthplanet0 Chắc chắn. Tôi đã thêm một số mã vào câu trả lời của mình. – kol
hey kol, cảm ơn thời gian của bạn. Tôi đã hỏi thêm một câu hỏi tại một liên kết khác. Bạn muốn có giải pháp từ bạn nếu bạn muốn ... http: //stackoverflow.com/questions/18568050/how-to-get-a-list-of-random-numbers-that-should-be-unique – tenthplanet0
Tạo một mảng chứa tất cả các số bạn muốn (hoặc bất kỳ thùng chứa ngôn ngữ của bạn sử dụng) trừ đi tất cả các số bạn không muốn và chọn ngẫu nhiên từ mảng.
Cảm ơn cho logic .... mảng của tôi sẽ phát triển lớn. Liệu logic này có hiệu quả về chi phí trong trường hợp so sánh lớn không? – tenthplanet0
Sử dụng hàm để tạo số ngẫu nhiên từ 1 đến 100, so với viết câu lệnh if, ví dụ: nếu số ngẫu nhiên bằng 5, 7, 17, 23, tạo lại số ngẫu nhiên, nếu không thì hãy sử dụng số ngẫu nhiên đã được tạo ở vị trí đầu tiên.
nếu danh sách của tôi sẽ lớn hơn? Tôi nghĩ rằng một lần nữa và nó sẽ tiếp tục kiểm tra các câu lệnh if – tenthplanet0
Đây là những gì tôi làm trong trường hợp này, nó không hoàn hảo nhưng hoạt động tốt cho tôi. Tôi thường làm điều đó chỉ cho 1 số nhưng đây là cách nó có thể cho một nhóm các số bị loại trừ:
Giả sử tôi muốn loại trừ [5, 7, 17, 23] từ ngẫu nhiên từ 1-100. Tôi luôn có sự thay thế cho từng số bị loại trừ như [6, 8, 18, 24]. Nếu số ngẫu nhiên rơi vào bất kỳ số nào bị loại trừ, tôi thay thế nó bằng sự thay thế của nó.
Tôi đến đây tìm kiếm một giải pháp tốt hơn nhưng tôi không thể tìm thấy bất kỳ giải pháp nào, vì vậy tôi đã kết thúc chia sẻ của tôi.
Nếu bạn quan tâm đến Big O, hãy xem thuật toán này. Nó giả định rằng mảng giá trị bị loại trừ được sắp xếp theo thứ tự tăng dần và chứa các giá trị trong phạm vi 0
và n-1
phạm vi (bao gồm).
public static int random_except_list(int n, int[] x)
{
Random r = new Random();
int result = r.Next(n - x.Length);
for (int i = 0; i < x.Length; i++)
{
if (result < x[i])
return result;
result++;
}
return result;
}
Nếu bạn gọi nó với:
random_except_list(8, new int[]{3,4,6})
nó sẽ trở lại một trong những giá trị sau: 0
, 1
, 2
, 5
, 7
.
Tôi nghĩ đó là cách tốt nhất để thực hiện. Cảm ơn bạn –
bạn có thể sử dụng câu lệnh do-while để chọn ngẫu nhiên khác nếu nó bằng số bạn muốn loại trừ. mã này là để loại trừ số bạn chọn trước khi
int newNumber;
do {
newNumber = Random.Range (0, 100);
} while(number == newNumber);
number = newNumber;
Đây là phương pháp Extention tôi sử dụng:
Random random = new Random();
public static int RandomNumber(int minN, int maxN, IEnumerable<int> exNumbers)
{
int result = exNumbers.First();
while (exNumbers.ToList().Contains(result))
{
result = random.Next(minN, maxN + 1);
}
return result;
}
gì ngôn ngữ bạn đang sử dụng ?? – Saint
Tôi đang sử dụng C# ... – tenthplanet0