Gibt es in C # eine Zwischenfunktion?


73

Google versteht nicht, dass "zwischen" der Name der gesuchten Funktion ist und gibt nichts Relevantes zurück.

Beispiel: Ich möchte in nur einer Operation prüfen, ob 5 zwischen 0 und 10 liegt


2
Es ist irgendwie mathematisch unmöglich, es mit einer Operation zu machen ... haben Sie versucht, Ihre eigene zu schreiben?
AK_

3
Die .NET-Bibliotheken haben nicht alle Funktionen unter der Sonne. Sie müssen noch einige Dinge selbst codieren;)
Byron Whitlock

2
Ich war neugierig, da SQL auch einen ZWISCHEN Operator hat. Schauen Sie
Tom

1
... was auch nicht die Funktion hat ...: - /
Peter C

MySql hat aber nicht c #
Ismail Gunes

Antworten:


92

Nein, aber Sie können Ihre eigenen schreiben:

public static bool Between(this int num, int lower, int upper, bool inclusive = false)
{
    return inclusive
        ? lower <= num && num <= upper
        : lower < num && num < upper;
}

3
Dies mag nützlich sein, aber Lambda-Ausdrücke erlauben keine Mitglieder mit optionalen Parametern. Ich werde stattdessen für eine Überladung gehen
;-)

10
Das ist kein Lambda. Es ist kleiner als oder gleich.
John Lord

130

Es ist nicht klar, was Sie unter "einer Operation" verstehen, aber nein, es gibt keine mir bekannte Operator- / Framework-Methode, um festzustellen, ob sich ein Element innerhalb eines Bereichs befindet.

Sie können natürlich selbst eine Erweiterungsmethode schreiben. In diesem Beispiel wird beispielsweise davon ausgegangen, dass das Intervall an beiden Endpunkten geschlossen ist .

public static bool IsBetween<T>(this T item, T start, T end)
{
    return Comparer<T>.Default.Compare(item, start) >= 0
        && Comparer<T>.Default.Compare(item, end) <= 0;
}

Und dann benutze es als:

bool b = 5.IsBetween(0, 10); // true

Wie würde sich dies für Typen verhalten, die nicht implementiert sind IComparable<T>oder IComparable?
Sam

13
@ Sam es wird eine Ausnahme auslösen, aber um dies zu vermeiden, können Sie hinzufügenwhere T : IComparable, IComparable<T>
WiiMaxx

Dies sollte die akzeptierte Lösung sein; wäre einfach genug, um auch einen "inklusive" Parameter hinzuzufügen.
System.Cats.Lol

1
Großartige Arbeit, aber wenn Sie nicht möchten, dass dies inklusive ist, und Sie möchten, dass diese 3 zwischen 5 und 2 (sowie zwischen 2 und 5) liegt, verwenden Sie diese:return Comparer<T>.Default.Compare(item, start) == -Comparer<T>.Default.Compare(item, end);
Mathieu

32

Hier ist eine komplette Klasse.

/// <summary>
/// An extension class for the between operation
/// name pattern IsBetweenXX where X = I -> Inclusive, X = E -> Exclusive
/// <a href="https://stackoverflow.com/a/13470099/37055"></a>
/// </summary>
public static class BetweenExtensions
{

    /// <summary>
    /// Between check <![CDATA[min <= value <= max]]> 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">the value to check</param>
    /// <param name="min">Inclusive minimum border</param>
    /// <param name="max">Inclusive maximum border</param>
    /// <returns>return true if the value is between the min & max else false</returns>
    public static bool IsBetweenII<T>(this T value, T min, T max) where T:IComparable<T>
    {
        return (min.CompareTo(value) <= 0) && (value.CompareTo(max) <= 0);
    }

    /// <summary>
    /// Between check <![CDATA[min < value <= max]]>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">the value to check</param>
    /// <param name="min">Exclusive minimum border</param>
    /// <param name="max">Inclusive maximum border</param>
    /// <returns>return true if the value is between the min & max else false</returns>
    public static bool IsBetweenEI<T>(this T value, T min, T max) where T:IComparable<T>
    {
        return (min.CompareTo(value) < 0) && (value.CompareTo(max) <= 0);
    }

    /// <summary>
    /// between check <![CDATA[min <= value < max]]>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">the value to check</param>
    /// <param name="min">Inclusive minimum border</param>
    /// <param name="max">Exclusive maximum border</param>
    /// <returns>return true if the value is between the min & max else false</returns>
    public static bool IsBetweenIE<T>(this T value, T min, T max) where T:IComparable<T>
    {
        return (min.CompareTo(value) <= 0) && (value.CompareTo(max) < 0);
    }

    /// <summary>
    /// between check <![CDATA[min < value < max]]>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">the value to check</param>
    /// <param name="min">Exclusive minimum border</param>
    /// <param name="max">Exclusive maximum border</param>
    /// <returns>return true if the value is between the min & max else false</returns>

    public static bool IsBetweenEE<T>(this T value, T min, T max) where T:IComparable<T>
    {
        return (min.CompareTo(value) < 0) && (value.CompareTo(max) < 0);
    }
}

plus einige Unit-Test-Code

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethodIsBeetween()
    {
        Assert.IsTrue(5.0.IsBetweenII(5.0, 5.0));
        Assert.IsFalse(5.0.IsBetweenEI(5.0, 5.0));
        Assert.IsFalse(5.0.IsBetweenIE(5.0, 5.0));
        Assert.IsFalse(5.0.IsBetweenEE(5.0, 5.0));

        Assert.IsTrue(5.0.IsBetweenII(4.9, 5.0));
        Assert.IsTrue(5.0.IsBetweenEI(4.9, 5.0));
        Assert.IsFalse(5.0.IsBetweenIE(4.9, 5.0));
        Assert.IsFalse(5.0.IsBetweenEE(4.9, 5.0));

        Assert.IsTrue(5.0.IsBetweenII(5.0, 5.1));
        Assert.IsFalse(5.0.IsBetweenEI(5.0, 5.1));
        Assert.IsTrue(5.0.IsBetweenIE(5.0, 5.1));
        Assert.IsFalse(5.0.IsBetweenEE(5.0, 5.1));

        Assert.IsTrue(5.0.IsBetweenII(4.9, 5.1));
        Assert.IsTrue(5.0.IsBetweenEI(4.9, 5.1));
        Assert.IsTrue(5.0.IsBetweenIE(4.9, 5.1));
        Assert.IsTrue(5.0.IsBetweenEE(4.9, 5.1));

        Assert.IsFalse(5.0.IsBetweenII(5.1, 4.9));
        Assert.IsFalse(5.0.IsBetweenEI(5.1, 4.9));
        Assert.IsFalse(5.0.IsBetweenIE(5.1, 4.9));
        Assert.IsFalse(5.0.IsBetweenEE(5.1, 4.9));

    }
}

7
T sollte IComparable <T> und nicht nur IComparable sein, sonst bekommt man Boxen
Mark Sowul

22

Nein, Sie müssen jeden Endpunkt einzeln testen.

if ((x > 0) && (x < 10)) {
   // do stuff
}

Oder wenn Sie wollen , dass es schauen mehr „betweeny“, Neuordnungs die argumente:

if ((0 < x) && (x < 10)) {
   // do stuff
}

15

Bisher hat anscheinend keine der Antworten die wahrscheinliche Möglichkeit in Betracht gezogen, dass Sie dynamisch nicht wissen, welcher Wert die Unter- und Obergrenze ist. Für den allgemeinen Fall könnten Sie Ihre eigene IsBetween-Methode erstellen, die wahrscheinlich ungefähr so ​​aussehen würde:

    public bool IsBetween(double testValue, double bound1, double bound2)
    {
        return (testValue >= Math.Min(bound1,bound2) && testValue <= Math.Max(bound1,bound2));
    }

11

In C # /. NET ist kein Konstrukt integriert, aber Sie können einfach Ihre eigene Erweiterungsmethode hinzufügen:

public static class ExtensionsForInt32
{
    public static bool IsBetween (this int val, int low, int high)
    {
           return val > low && val < high;
    }
}

Welches kann verwendet werden wie:

if (5.IsBetween (0, 10)) { /* Do something */ }

+1. Die einzige Einschränkung wäre, dem Verbraucher die Erwartung zu setzen, dass die Randfälle (0 und 10) NICHT inklusive sind. Ansonsten ist das super!
p.campbell

Ich habe eine Kombination dieser und der von Ani vorgeschlagenen Methode verwendet. Ich habe die IsBetween-Funktion meiner Erweiterungsklasse als privates Mitglied hinzugefügt. Dann habe ich ähnliche öffentliche Funktionen verwendet, um die spezifischen Typen anzuzeigen, die ich erweitern wollte, und die die private Funktion aufrufen.
JRodd

5

Generische Funktion, die bei der Kompilierung validiert wird!

public static bool IsBetween<T>(this T item, T start, T end) where T : IComparable
{
    return item.CompareTo(start) >= 0 && item.CompareTo(end) <= 0;
}

4

Mit Ausnahme der Antwort von @Ed G müssen alle Antworten wissen, welche Grenze die untere und welche die obere ist.

Hier ist eine (eher nicht offensichtliche) Möglichkeit, dies zu tun, wenn Sie nicht wissen, welche Grenze welche ist.

  /// <summary>
  /// Method to test if a value is "between" two other values, when the relative magnitude of 
  /// the two other values is not known, i.e., number1 may be larger or smaller than number2. 
  /// The range is considered to be inclusive of the lower value and exclusive of the upper 
  /// value, irrespective of which parameter (number1 or number2) is the lower or upper value. 
  /// This implies that if number1 equals number2 then the result is always false.
  /// 
  /// This was extracted from a larger function that tests if a point is in a polygon:
  /// http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
  /// </summary>
  /// <param name="testValue">value to be tested for being "between" the other two numbers</param>
  /// <param name="number1">one end of the range</param>
  /// <param name="number2">the other end of the range</param>
  /// <returns>true if testValue >= lower of the two numbers and less than upper of the two numbers,
  ///          false otherwise, incl. if number1 == number2</returns>
  private static bool IsInRange(T testValue, T number1, T number2)
  {
     return (testValue <= number1) != (testValue <= number2);
  }

Hinweis: Dies ist KEINE generische Methode. es ist Pseudocode. Das T in der obigen Methode sollte durch einen geeigneten Typ ersetzt werden, "int" oder "float" oder was auch immer. (Es gibt Möglichkeiten, dieses Generikum zu erstellen, aber sie sind so chaotisch, dass es sich für eine einzeilige Methode nicht lohnt, zumindest in den meisten Situationen nicht.)


2
Programmierer haben Logik wie diese verstanden :)
Fattie

Mir ist klar, dass dies in der Internetzeit "uralt" ist, aber ich mag diese Lösung WIRKLICH, zumal der Anrufer nicht wissen muss, welche Grenze welche ist.
Andrew Steitz

4

Wäre es nicht so einfach wie

0 < 5 && 5 < 10

?

Wenn Sie also eine Funktion daraus haben möchten, können Sie diese einfach einer Utility-Klasse hinzufügen:

public static bool Between(int num, int min, int max) {
    return min < num && num < max;
}

Ich habe so etwas wie bool x = Math.between (5,0,10) erwartet, aber ich denke, es existiert nicht, also muss ich mich an die größeren / kleineren Zeichen halten
Mathieu

Nun, ich nehme an, Sie könnten Erweiterungsmethoden verwenden.
Peter C

Wadda, weißt du, sieh dir Petes Antwort an.
Peter C

Der Rückgabetyp sollte boolnicht sein void.
Emanuel Vintilă

3
int val_to_check = 5
bool in_range = Enumerable.Range(0, 13).Contains(val_to_check);

Der zweite Parameter ist die "Anzahl", nicht das Ende oder die hohe Zahl.

IE

int low_num = 0
int high_num = 12
int val_to_check = 5
bool in_range = Enumerable.Range(low_num , high_num - low_num + 1).Contains(val_to_check);

Überprüft, ob der Wert für val_to_check zwischen 0 und 12 liegt


3

Siehe diesen Link. Eine einzeilige Lösung für diese Frage.

Wie kann ich elegant prüfen, ob eine Zahl innerhalb eines Bereichs liegt?

int x = 30;
if (Enumerable.Range(1,100).Contains(x))
//true

if (x >= 1 && x <= 100)
//true

Ich weiß, dass der Beitrag ziemlich alt ist, aber er kann anderen helfen.


1
Wenn es sich bei dieser Frage um ein Duplikat der Frage handelt, die Sie hier verlinkt haben, kennzeichnen Sie sie bitte als Duplikat mit der Schaltfläche "Markieren" unter der Frage, anstatt eine entsprechende Antwort zu hinterlassen. Wenn es sich nicht um ein Duplikat handelt, hinterlassen Sie bitte eine vollständige Antwort anstelle einer Nur-Link-Antwort.
Josliber

2

Wie wäre es mit

somenumber == Math.Max(0,Math.Min(10,somenumber));

gibt true zurück, wenn somenumber 5 ist. gibt false zurück, wenn somenumber 11 ist.


1

Wie @Hellfrost betonte, ist es buchstäblich Unsinn, eine Zahl mit zwei verschiedenen Zahlen in "einer Operation" zu vergleichen, und ich kenne keinen C # -Operator, der dies kapselt.

between = (0 < 5 && 5 < 10);

Ist über die kompakteste Form, die ich mir vorstellen kann.

Sie könnten eine etwas "flüssig" aussehende Methode mit der Erweiterung erstellen (obwohl es amüsant ist, denke ich, dass es übertrieben ist):

public static bool Between(this int x, int a, int b)
{
    return (a < x) && (x < b);
}

Verwenden:

int x = 5;
bool b = x.Between(0,10);

Damit dies in c # NICHT existiert, weiß ich sicher, dass dies in Python nativ unterstützt wird
Davide Piras

Dies liegt daran, dass Batterien separat mit C # erhältlich sind. ;)
Peter C

0

Ich kenne diese Funktion nicht. Wenn Ihr Wert nicht signiert ist, bedeutet nur eine Operation (Wert <11) ... Wenn er signiert ist, gibt es meines Erachtens keinen atomaren Weg, dies zu tun, da 10 keine Potenz von 2 ist ...


0

Base @Dan J dieser Version ist Max / Min egal, eher wie SQL :)

public static bool IsBetween(this decimal me, decimal a, decimal b, bool include = true)
{
    var left = Math.Min(a, b);
    var righ = Math.Max(a, b);

    return include
        ? (me >= left && me <= righ)
        : (me > left && me < righ)
    ;
}

0

Oder wenn Sie den Wert an das Intervall binden möchten:

public static T EnsureRange<T>(this T value, T min, T max) where T : IComparable<T>
    {
        if (value.CompareTo(min) < 0)
            return min;
        else if (value.CompareTo(max) > 0)
            return max;
        else
            return value;
    }

Es ist wie zweiseitiges Math.Min / Max


0

Und für negative Werte:

    Public Function IsBetween(Of T)(item As T, pStart As T, pEnd As T) As Boolean ' https://msdn.microsoft.com/fr-fr/library/bb384936.aspx
    Dim Deb As T = pStart
    Dim Fin As T = pEnd
    If (Comparer(Of T).Default.Compare(pStart, pEnd) > 0) Then Deb = pEnd : Fin = pStart
    Return Comparer(Of T).Default.Compare(item, Deb) >= 0 AndAlso Comparer(Of T).Default.Compare(item, Fin) <= 0
End Function
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.