क्या पूर्णांक श्रेणी का प्रतिनिधित्व करने के लिए C # प्रकार है?


105

मुझे एक पूर्णांक श्रेणी को संग्रहीत करने की आवश्यकता है। क्या C # 4.0 में इसके लिए कोई मौजूदा प्रकार है?

बेशक, मैं अपनी कक्षा को गुणों के साथ लिख सकता हूं int Fromऔर int Toयह सुनिश्चित करने के लिए उचित तर्क का निर्माण कर सकता हूं From <= To। लेकिन अगर एक प्रकार पहले से मौजूद है, तो मैं निश्चित रूप से इसका उपयोग करूंगा।


2
मुझे लगता है कि स्वीकृत उत्तर को बदला जाना चाहिए। @ रेस्ना का जवाब Enumerable.Rangeहै, मैंने जो देखा है, वह सी # 3.0 में श्रेणियों को लागू करने का वास्तविक तरीका है। और सी # 3.0 2007 के बाद से करीब है, इसलिए इस बिंदु पर 9 साल है।
एहतेश चौधरी

@EhteshChoudhury ओपी असतत मूल्यों को संभालने के बारे में कुछ भी उल्लेख नहीं करता है, या यहां तक ​​कि एक मिनट और अधिकतम के लिए उन प्रकारों को मान्य करता है, जो कि Enumerable.Rangeपूरा करता है। ओपी बस एक मौजूदा डेटा संरचना की तलाश में था जो अंतराल को संभालती है जिसमें कम और ऊपरी बाउंड के गुण हो सकते हैं, और कुछ भी नहीं (इसके अलावा कुछ व्यवहार को लागू करने वाले तरीकों के अलावा)।
सनी पटेल

2
@EesheshChoudhury मैं अपनी आवाज़ को "Enumerable.Range" का उपयोग न करने के लिए जोड़ूंगा। न्यूनतम / अधिकतम मानों की एक जोड़ी पर पकड़ की सरल समस्या को हल करने के लिए यह एक गुप्त तरीका है। Enumerable.Max (IEnumerable <int>) (या Enumerable.Min) को हर कॉल सीमा का पता लगाने के लिए पूरी सीमा पर पुनरावृत्त करता है। जैसा कि दूसरों ने कहा है, कि बहुत सारे पुनरावृत्तियां हो सकती हैं : हम यहां माइक्रो प्रदर्शन ट्यूनिंग नहीं कर रहे हैं, हम बात कर रहे हैं अपंगता। इस तरह की प्रोग्रामिंग इसका कारण है। नेट को प्रदर्शन के लिए एक (अन्यायपूर्ण) बुरा नाम मिलता है! स्वीकृत उत्तर और समान उत्तर केवल व्यावहारिक समाधान हैं।
डैनियल स्कॉट

1
ये उचित है। Enumerable.Range(1,1000000) के लिए अधिक रेंज स्पेसटाइप के लिए (1,1000000) के लिए अधिक स्थान लेगा। मैंने प्रश्न को पहली बार गलत तरीके से पढ़ा था और सोचा था कि यह पूछ रहा थाEnumerable.Range
एहतेश चौधरी

1
@EhteshChoudhury Enumerable.Range 1,1000000 नहीं ले जाएगा कम से कम आप ToList () विधि कहते हैं।
लुइस

जवाबों:


136

मुझे अपना रोल करना सबसे अच्छा लगा। कुछ लोग Tupleएस या Pointएस का उपयोग करते हैं , लेकिन अंत में आप चाहते हैं कि आपका Rangeव्यापक हो और कुछ आसान तरीके प्रदान करें जो एक से संबंधित हैं Range। यह सबसे अच्छा है अगर जेनेरिक (क्या होगा यदि आपको किसी श्रेणी की आवश्यकता है Double, या कुछ कस्टम वर्ग की सीमा?) उदाहरण के लिए:

/// <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);
    }
}

13
उस समय, मुझे यकीन नहीं था कि IComparableऑपरेटर ओवरलोड की गारंटी देगा। मुझे एक CompareToविधि की गारंटी है , इसलिए वह उपयोग है।
डेहरीस

14
पता चला कि मैं ऐसा करने में सही था: stackoverflow.com/questions/5101378/…
drharris

2
के structबजाय बेहतर हो सकता है class?
17

2
@Will हे आदमी नंगेपन के दस्तावेज़ों का ज्ञान नहीं देते। :)
डेहरिस 16

7
बहुत मददगार, धन्यवाद! एक निर्माता को क्यों नहीं जोड़ा जाता है जो आपको इसे तुरंत शुरू करने की अनुमति देता है? public Range(T min, T max) { Minimum = min; Maximum = max; }
NateJC

8

बस एक छोटी सी कक्षा मैंने लिखी है जो किसी के लिए सहायक हो सकती है:

    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

4
मैं वास्तव में फंक्शन को पसंद करता हूं
ड्रैगनबॉर्न

वह understandफंक्शन कूल है। अगर मैंने इसे हमारे कोड में एक समीक्षा में देखा, तो मैं इसका नाम बदलने का सुझाव दूंगा Set, क्योंकि Range(मेरे लिए) निरंतर लगता है।
डीएलडब्ल्यू

7

रंग और संकेत 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/ और अधिक विस्तार के लिए।


यह एक अलग अवधारणा है और ओपी के अनुसार नहीं चाहता था।
पेपिटोश जूल

System.Rangeप्रकार केवल स्वीकार करता है int, हालांकि।
snipsnipsnip

यह उल्लेख करना महत्वपूर्ण है कि यह केवल .NET कोर 3.0 के बाद से उपलब्ध है। यह .NET फ्रेमवर्क में उपलब्ध नहीं है।
सर्र्स

2

इसे और अधिक मुहावरेदार और आसानी से अनुकूलन योग्य बनाने के लिए @ 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");
    }

2

इस तरह एक विस्तार विधि लिखें

 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
}

1
क्यों if (value >= from && value <= to) return true;और क्या नहीं return (value >= from && value <= to)?
sdgfsdh

2

@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
}

1

इसके अलावा, यहां एक अलग स्पर्शरेखा का एक सा है, लेकिन कभी-कभी पर्वतमाला केवल उन पर पुनरावृत्ति करने के लिए उपयोगी होती हैं, थोड़ा सा यह अजगर में करने के लिए प्रथागत है। उस स्थिति में, System.Linqनाम स्थान एक static IEnumerable<int> Range(Int32, Int32)विधि को परिभाषित करता है , जो हस्ताक्षर के रूप में सुझाता है,

एक निर्दिष्ट सीमा के भीतर अभिन्न संख्याओं का एक क्रम उत्पन्न करता है

MSDN पर प्रलेखन और उदाहरण देखें


@ यह तब से नहीं होना चाहिए जब से एनुमरेबल रेंज स्टार्ट और काउंट को स्वीकार कर लेती है।
राशिद

@ राशिद मेला काफी लेकिन मैं वास्तव में इसे एक समस्या नहीं मानता। मुझे पता है कि ओपी ने एक "वर्ग के साथ " int Fromऔर int To"के लिए कहा था, लेकिन मुझे पूरा विश्वास है कि यह एक विशिष्ट आवश्यकता नहीं थी, बल्कि उनकी बात को स्पष्ट करने के लिए कुछ था। रुचि रखने वाले के लिए, निश्चित रूप से, countपैरामीटर का मूल्य बहुत आसानी से निर्धारित किया जा सकता है, बशर्ते कि आपके पास पहले से ही int Fromऔर int Toचर हैं।
गाबिक

1

एक Enumerable.Rangeविधि है, लेकिन यह स्वीकार करता है startऔर countइसके पैरामीटर के रूप में। आदेश में यह काम करने के लिए जैसा आप चाहते हैं startऔर end, endसूत्र होगाend - start + 1

उपयोग:

Enumerable.Range(start, end - start + 1).ToList()


0

चूँकि मुझे C # में अंतराल भी याद आ रहा था, मैंने एक पूरी तरह से सामान्य अंतराल वर्ग को लागू किया , जो अधिक जटिल प्रकारों के साथ अंतराल का भी ध्यान रख सकता है, उदाहरण के लिए दो के बीच एक अंतराल DateTime, जिसमें TimeSpanगणना के दौरान शामिल है ।

एक उदाहरण उपयोग मामला, जहां एक GUI तत्व एक समय अंतराल का प्रतिनिधित्व करता है:

// Mockup of a GUI element and mouse position.
var timeBar = new { X = 100, Width = 200 };
int mouseX = 180;

// Find out which date on the time bar the mouse is positioned on,
// assuming it represents whole of 2014.
var timeRepresentation = new Interval<int>( timeBar.X, timeBar.X + timeBar.Width );
DateTime start = new DateTime( 2014, 1, 1 );
DateTime end = new DateTime( 2014, 12, 31 );
var thisYear = new Interval<DateTime, TimeSpan>( start, end );
DateTime hoverOver = timeRepresentation.Map( mouseX, thisYear );

// If the user clicks, zoom in to this position.
double zoomLevel = 0.5;
double zoomInAt = thisYear.GetPercentageFor( hoverOver );
Interval<DateTime, TimeSpan> zoomed = thisYear.Scale( zoomLevel, zoomInAt );

// Iterate over the interval, e.g. draw labels.
zoomed.EveryStepOf( TimeSpan.FromDays( 1 ), d => DrawLabel( d ) );

समर्थित कार्यक्षमता के अधिक व्यापक प्रतिनिधित्व के लिए यूनिट परीक्षण देखें

कवर के तहत यह रन टाइम पर टाइप ऑपरेटर ऑपरेटर को संकलित करने के लिए एक्सप्रेशन ट्री का उपयोग करता है , जो कि कैश किए जाते हैं इसलिए पहली बार टाइप शुरू होने पर केवल एक लागत होती है।


-2

कैसे एक संरचना के बारे में ?


2
जब तक आप नहीं जानते कि मैं एक संरचना का उपयोग नहीं करूंगा जब तक कि मिनट और अधिकतम मान एक बार में बदल नहीं जाएंगे ।
आइब्रेट

यह "पहले से मौजूद" प्रश्न का उत्तर देता है। संरचना प्रकार विशेष रूप से उस प्रकार के लिए मौजूद है जैसे प्रश्न में।
जेम्स सुमेर १ners

3
संरचना अपने आप में एक प्रकार नहीं है। आप मूल रूप से कह रहे हैं "नो गो क्रिएट योर टाइप" - यह एक कानूनी जवाब है
रॉबर्ट लेवी

2
पहले तीन शब्द "struct प्रकार ...": जुड़े हुए दस्तावेज में आप से असहमत
जेम्स Sumners

मैं jsumners से सहमत हूं। एक संरचना ऐसा करने का एक आसान और सीधा-सरल तरीका है, और यह कोड के 2 पृष्ठों का उत्पादन नहीं करता है जिन्हें बाद में इस तरह की सरल समस्या के लिए बनाए रखा जाना चाहिए। आप एक ही चीज़ के लिए एक जोड़ी <...> का भी उपयोग कर सकते हैं। Microsoft विभिन्न स्थानों पर संरचनाओं के अपरिवर्तनीय होने के बारे में अपने स्वयं के "नियम" को तोड़ता है।
टॉम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.