정수 범위를 저장할 필요가 있습니다. C # 4.0에 기존 유형이 있습니까?
물론 int From
및 int To
속성을 사용 하여 고유 한 클래스를 작성 하고 From <= To
. 그러나 유형이 이미 존재하는 경우에는 당연히 그것을 사용합니다.
답변
나는 내 자신을 굴리는 것이 가장 좋다는 것을 알았다. 어떤 사람들은 Tuple
s 또는 Point
s를 사용하지만 결국에는 Range
광범위하고 Range
. 일반적인 경우에도 가장 좋습니다 ( Double
s 범위 또는 일부 사용자 지정 클래스 범위가 필요한 경우 어떻게 됩니까?). 예 :
/// <summary>The Range class.</summary>
/// <typeparam name="T">Generic parameter.</typeparam>
public class Range<T> where T : IComparable<T>
{
/// <summary>Minimum value of the range.</summary>
public T Minimum { get; set; }
/// <summary>Maximum value of the range.</summary>
public T Maximum { get; set; }
/// <summary>Presents the Range in readable format.</summary>
/// <returns>String representation of the Range</returns>
public override string ToString()
{
return string.Format("[{0} - {1}]", this.Minimum, this.Maximum);
}
/// <summary>Determines if the range is valid.</summary>
/// <returns>True if range is valid, else false</returns>
public bool IsValid()
{
return this.Minimum.CompareTo(this.Maximum) <= 0;
}
/// <summary>Determines if the provided value is inside the range.</summary>
/// <param name="value">The value to test</param>
/// <returns>True if the value is inside Range, else false</returns>
public bool ContainsValue(T value)
{
return (this.Minimum.CompareTo(value) <= 0) && (value.CompareTo(this.Maximum) <= 0);
}
/// <summary>Determines if this Range is inside the bounds of another range.</summary>
/// <param name="Range">The parent range to test on</param>
/// <returns>True if range is inclusive, else false</returns>
public bool IsInsideRange(Range<T> range)
{
return this.IsValid() && range.IsValid() && range.ContainsValue(this.Minimum) && range.ContainsValue(this.Maximum);
}
/// <summary>Determines if another range is inside the bounds of this range.</summary>
/// <param name="Range">The child range to test</param>
/// <returns>True if range is inside, else false</returns>
public bool ContainsRange(Range<T> range)
{
return this.IsValid() && range.IsValid() && this.ContainsValue(range.Minimum) && this.ContainsValue(range.Maximum);
}
}
답변
누군가에게 도움이 될 수있는 내가 작성한 작은 수업 :
public class Range
{
public static List<int> range(int a, int b)
{
List<int> result = new List<int>();
for(int i = a; i <= b; i++)
{
result.Add(i);
}
return result;
}
public static int[] Understand(string input)
{
return understand(input).ToArray();
}
public static List<int> understand(string input)
{
List<int> result = new List<int>();
string[] lines = input.Split(new char[] {';', ','});
foreach (string line in lines)
{
try
{
int temp = Int32.Parse(line);
result.Add(temp);
}
catch
{
string[] temp = line.Split(new char[] { '-' });
int a = Int32.Parse(temp[0]);
int b = Int32.Parse(temp[1]);
result.AddRange(range(a, b).AsEnumerable());
}
}
return result;
}
}
그런 다음 전화하십시오.
Range.understand("1,5-9,14;16,17;20-24")
결과는 다음과 같습니다.
List<int>
[0]: 1
[1]: 5
[2]: 6
[3]: 7
[4]: 8
[5]: 9
[6]: 14
[7]: 16
[8]: 17
[9]: 20
[10]: 21
[11]: 22
[12]: 23
[13]: 24
답변
범위 및 인덱스는 C # 8.0과 함께 릴리스됩니다.
이제 할 수 있습니다
string[] names =
{
"Archimedes", "Pythagoras", "Euclid", "Socrates", "Plato"
};
foreach (var name in names[1..4])
{
yield return name;
}
자세한 내용은 https://blogs.msdn.microsoft.com/dotnet/2018/12/05/take-c-8-0-for-a-spin/ 을 확인 하세요.
답변
@ andrius-naruševičius를 개선하면 좀 더 관용적이고 쉽게 사용자 정의 할 수있는 매우 유용한 답변입니다.
/// <summary>
/// http://stackoverflow.com/questions/5343006/is-there-a-c-sharp-type-for-representing-an-integer-range
/// </summary>
public class Range
{
readonly static char[] Separators = {','};
public static List<int> Explode(int from, int to)
{
return Enumerable.Range(from, (to-from)+1).ToList();
}
public static List<int> Interpret(string input)
{
var result = new List<int>();
var values = input.Split(Separators);
string rangePattern = @"(?<range>(?<from>\d+)-(?<to>\d+))";
var regex = new Regex(rangePattern);
foreach (string value in values)
{
var match = regex.Match(value);
if (match.Success)
{
var from = Parse(match.Groups["from"].Value);
var to = Parse(match.Groups["to"].Value);
result.AddRange(Explode(from, to));
}
else
{
result.Add(Parse(value));
}
}
return result;
}
/// <summary>
/// Split this out to allow custom throw etc
/// </summary>
private static int Parse(string value)
{
int output;
var ok = int.TryParse(value, out output);
if (!ok) throw new FormatException($"Failed to parse '{value}' as an integer");
return output;
}
}
및 테스트 :
[Test]
public void ExplodeRange()
{
var output = Range.Explode(5, 9);
Assert.AreEqual(5, output.Count);
Assert.AreEqual(5, output[0]);
Assert.AreEqual(6, output[1]);
Assert.AreEqual(7, output[2]);
Assert.AreEqual(8, output[3]);
Assert.AreEqual(9, output[4]);
}
[Test]
public void ExplodeSingle()
{
var output = Range.Explode(1, 1);
Assert.AreEqual(1, output.Count);
Assert.AreEqual(1, output[0]);
}
[Test]
public void InterpretSimple()
{
var output = Range.Interpret("50");
Assert.AreEqual(1, output.Count);
Assert.AreEqual(50, output[0]);
}
[Test]
public void InterpretComplex()
{
var output = Range.Interpret("1,5-9,14,16,17,20-24");
Assert.AreEqual(14, output.Count);
Assert.AreEqual(1, output[0]);
Assert.AreEqual(5, output[1]);
Assert.AreEqual(6, output[2]);
Assert.AreEqual(7, output[3]);
Assert.AreEqual(8, output[4]);
Assert.AreEqual(9, output[5]);
Assert.AreEqual(14, output[6]);
Assert.AreEqual(16, output[7]);
Assert.AreEqual(17, output[8]);
Assert.AreEqual(20, output[9]);
Assert.AreEqual(21, output[10]);
Assert.AreEqual(22, output[11]);
Assert.AreEqual(23, output[12]);
Assert.AreEqual(24, output[13]);
}
[ExpectedException(typeof (FormatException))]
[Test]
public void InterpretBad()
{
Range.Interpret("powdered toast man");
}
답변
다음과 같은 확장 메서드를 작성하십시오.
public static class NumericExtentions
{
public static bool InRange(this int value, int from, int to)
{
if (value >= from && value <= to)
return true;
return false;
}
public static bool InRange(this double value, double from, double to)
{
if (value >= from && value <= to)
return true;
return false;
}
}
우아하게 사용하세요
if (age.InRange(18, 39))
{
//Logic
}
답변
@drharris의 답변에서 영감을 얻은이 구현을 사용하면 포괄적 / 배타적 일 수있는 값으로 적절한 수학적 간격을 정의 할 수 있습니다.
/// <summary>The Interval class.</summary>
/// <typeparam name="T">Generic parameter.</typeparam>
public class Interval<T> : IEquatable<Interval<T>>
where T : IComparable<T>, IEquatable<T>
{
public Interval()
{ }
public Interval(IntervalValue<T> minimum, IntervalValue<T> maximum)
{
this.Minimum = minimum;
this.Maximum = maximum;
}
/// <summary>Minimum value of the interval.</summary>
public IntervalValue<T>? Minimum { get; set; }
/// <summary>Maximum value of the interval.</summary>
public IntervalValue<T>? Maximum { get; set; }
/// <summary>Presents the Interval in readable format.</summary>
/// <returns>String representation of the Interval</returns>
public override string ToString()
{
var min = this.Minimum;
var max = this.Maximum;
var sb = new StringBuilder();
if (min.HasValue)
sb.AppendFormat(min.Value.ToString(IntervalNotationPosition.Left));
else
sb.Append("(-∞");
sb.Append(',');
if (max.HasValue)
sb.AppendFormat(max.Value.ToString(IntervalNotationPosition.Right));
else
sb.Append("∞)");
var result = sb.ToString();
return result;
}
/// <summary>Determines if the interval is valid.</summary>
/// <returns>True if interval is valid, else false</returns>
public bool IsValid()
{
var min = this.Minimum;
var max = this.Maximum;
if (min.HasValue && max.HasValue)
return min.Value.Value.CompareTo(max.Value.Value) <= 0;
return true;
}
/// <summary>Determines if the provided value is inside the interval.</summary>
/// <param name="x">The value to test</param>
/// <returns>True if the value is inside Interval, else false</returns>
public bool ContainsValue(T x)
{
if (x == null)
throw new ArgumentNullException(nameof(x));
var min = this.Minimum;
var max = this.Maximum;
var isValid = this.IsValid();
if (!isValid)
throw new InvalidOperationException("Interval is not valid.");
bool result = true; // (-∞,∞)
if (min.HasValue)
{
if (min.Value.Type == IntervalValueType.Exclusive)
result &= min.Value.Value.CompareTo(x) < 0;
else if (min.Value.Type == IntervalValueType.Inclusive)
result &= min.Value.Value.CompareTo(x) <= 0;
else
throw new NotSupportedException();
}
if (max.HasValue)
{
if (max.Value.Type == IntervalValueType.Exclusive)
result &= max.Value.Value.CompareTo(x) > 0;
else if (max.Value.Type == IntervalValueType.Inclusive)
result &= max.Value.Value.CompareTo(x) >= 0;
else
throw new NotSupportedException();
}
return result;
}
public bool Equals(Interval<T> other)
{
if (other == null)
return false;
if (ReferenceEquals(this, other))
return true;
return this.Minimum?.Equals(other.Minimum) == true
&& this.Maximum?.Equals(other.Maximum) == true;
}
public override bool Equals(object obj)
{
return this.Equals(obj as Interval<T>);
}
public override int GetHashCode()
{
unchecked
{
int hash = (int)2166136261;
hash = hash * 16777619 ^ this.Minimum?.GetHashCode() ?? 0;
hash = hash * 16777619 ^ this.Maximum?.GetHashCode() ?? 0;
return hash;
}
}
}
public struct IntervalValue<T> : IEquatable<IntervalValue<T>>
where T : IComparable<T>, IEquatable<T> //, IFormattable
{
private readonly T value;
private readonly IntervalValueType type;
public IntervalValue(T value, IntervalValueType type)
{
if (value == null)
throw new ArgumentNullException(nameof(value));
this.value = value;
this.type = type;
}
public T Value
{
get { return this.value; }
}
public IntervalValueType Type
{
get { return this.type; }
}
public bool Equals(IntervalValue<T> other)
{
return this.value.Equals(other.value)
&& this.type == other.type;
}
public override bool Equals(object obj)
{
return obj is IntervalValue<T> && this.Equals((IntervalValue<T>)obj);
}
public override int GetHashCode()
{
unchecked
{
int hash = (int)2166136261;
hash = hash * 16777619 ^ this.value.GetHashCode();
hash = hash * 16777619 ^ this.type.GetHashCode();
return hash;
}
}
internal string ToString(IntervalNotationPosition position)
{
var notation = this.Type.ToString(position);
switch (position)
{
case IntervalNotationPosition.Left:
return string.Format("{0}{1}", notation, this.Value);
case IntervalNotationPosition.Right:
return string.Format("{0}{1}", this.Value, notation);
default:
throw new NotSupportedException();
}
}
}
internal static class IntervalValueTypeExtensions
{
public static string ToString(this IntervalValueType type, IntervalNotationPosition position)
{
switch (position)
{
case IntervalNotationPosition.Left:
switch (type)
{
case IntervalValueType.Inclusive: return "[";
case IntervalValueType.Exclusive: return "(";
default:
throw new NotSupportedException();
}
case IntervalNotationPosition.Right:
switch (type)
{
case IntervalValueType.Inclusive: return "]";
case IntervalValueType.Exclusive: return ")";
default:
throw new NotSupportedException();
}
break;
default:
throw new NotSupportedException();
}
}
}
public enum IntervalValueType
{
Inclusive,
Exclusive
}
public enum IntervalNotationPosition
{
Left,
Right
}
답변
또한 여기에 약간 다른 탄젠트가 있지만 때로는 범위가 파이썬에서 수행하는 관례적인 것처럼 반복하는 데에만 유용합니다. 이 경우 System.Linq
네임 스페이스는 static IEnumerable<int> Range(Int32, Int32)
서명에서 알 수 있듯이 다음과 같은 메서드를 정의 합니다.
지정된 범위 내에서 일련의 정수를 생성합니다.