2010-12-10 13 views
3

Jeder! Wie kann ich einen minimalen Wert eines int-Arrays in einem bestimmten Bereich in C# erhalten? Zum Beispiel: int [] Array = neu int {1,2,3,4,5,6,7,8,76,45}; Und ich möchte einen minimalen Wert zwischen 3-und 8-ten Element erhalten. Vielleicht ist es möglich, über LINQ-Abfragen zu erhalten?C# -Arrays Minimalwert in einem bestimmten Bereich

+0

Wird es immer mindestens 8 Elemente haben? – ChaosPandion

Antwort

12
array.Skip(2).Take(5).Min(); 
+0

Wow, das ist toll :) Danke, decyclone;) – Nozim

+3

@nozim: Nein, es ist nicht, weil es nicht sofort klar ist, was es tut. Es ist clever und sieht clever aus, aber es ist nicht die lesbarste Lösung und sollte daher abgelehnt werden. Es tut uns leid. – jason

+6

@Jason: Überspringe 2 Gegenstände, nimm 5 Gegenstände und dann die min. Was ist nicht klar? – poindexter12

3
int min = array.Where((value, index) => index >= 2 && index <= 7).Min(); 

EDIT

Eigentlich über dem Ansatz ist sehr ineffizient, weil es die ganze Sequenz aufzählt, auch wenn wir in den Punkten mit einem Index von mehr als 7. Eine bessere Lösung nicht interessiert sind wäre TakeWhile zu verwenden:

int min = array.TakeWhile((value, index) => index <= 7).Skip(2).Min(); 

Leider ist es nicht sehr gut lesbar ... Die beste Option, es schöner zu machen, ist wahrscheinlich eine benutzerdefinierte Erweiterung Methode, wie sho zu erstellen wn in Jons Antwort.

2
int[] arr = {0,1,2,3,4,5,6,7,8}; 
int start = 3; 
int end = 8; 
int min = arr.Skip(start - 1).Take(end - start).Min(); 
2

nur eine weitere Option hinzuzufügen:

int start = 3; 
int end = 8; 
var min = Enumerable.Range(start - 1,end - start).Select(idx => array[idx]).Min(); 

AFAIK ist dies "theorically" schneller, wenn Sie einen Bereich in der Nähe des Endes der einen nehmen, und Ihr Array ist wirklich sehr lang.

Das ist, weil (wieder AFAIK) Skip() berücksichtigt nicht, dass ein Array ist (d. H. Zufällig in O (1) zugegriffen werden kann) und zählt es trotzdem auf.

+1

Ja, es ist schneller in dem speziellen Fall der Verwendung eines Arrays (oder anderen 'IList ') - aber natürlich fällt es in der allgemeinen Sequenz Fall auseinander. Natürlich könnte 'Skip' auch in einer zukünftigen Version behoben werden. –

+0

Natürlich, und ich hoffe wirklich, dass es behoben wird. In der Zwischenzeit war meine nur eine Art Warnung :) – digEmAll

+0

+1 für die Warnung, auch wenn es nicht die Lösung ist, die ich normalerweise wählen würde :) –

6

Ich denke, ich kann meine Tuppence dazu hinzufügen.

public static IEnumerable<T> WithIndexBetween<T>(this IEnumerable<T> source, 
    int startInclusive, int endExclusive) 
{ 
    // The two values can be the same, yielding no results... but they must 
    // indicate a reasonable range 
    if (endExclusive < startInclusive) 
    { 
     throw new ArgumentOutOfRangeException("endExclusive"); 
    } 
    return source.Skip(startInclusive).Take(endExclusive - startInclusive); 
} 

Dann: Als Jason auf die Tatsache, Objekte, die wir sagen, wie viele wir das Überspringen eher als Ende Index, können wir eine einfache Erweiterung Methode hinzufügen

int min = array.WithIndexBetween(2, 7).Min(); 

die Verlängerung einstellen Methodenname nach Geschmack. (Naming ist hart, und ich werde nicht im Alter mit einem schönen man hier :)

+0

Ja, es ist gut, denn jetzt liest es sich wie die Problemstellung. Beachten Sie, dass es liest wie "nimmt diese Werte in der Reihenfolge mit Index zwischen zwei und sieben, inklusive, und nehmen Sie das Minimum", wie Thomas mir liest, weshalb ich es an erster Stelle bevorzugte. Also, ich mag das. – jason

+0

Ich war im Begriff, meine Antwort mit etwas ähnlichem zu aktualisieren, dann sah ich deine Antwort ... –

+0

Jon, das ist Awesome! Ich liebe Erweiterungsmethoden. Und Jason, ich mag deine Hartnäckigkeit und das auch gegen Jon Skeet! :) – decyclone

0

persönlich kommen verbringen, würde ich das vorziehen:

public static class ArrayExtensions { 
    public static bool ArrayAndIndexesAreValid(
     T[] array, 
     int startInclusive, 
     int endExclusive 
    ) { 
    return array != null && 
      array.Length > 0 && 
      startInclusive >= 0 && startInclusive < array.Length && 
      endExclusive >= 1 && endExclusive <= array.Length && 
      startInclusive < endExclusive; 
    } 
    public static IEnumerable<T> Slice<T>(
     this T[] array, 
     int startInclusive, 
     int endExclusive 
    ) { 
     Contract.Requires<ArgumentException>(ArrayAndIndexesAreValid(
      array, 
      startInclusive, 
      endExclusive) 
     ); 
     for (int index = startInclusive; index < endExclusive; index++) { 
      yield return array[index]; 
     } 
    } 
    public static T MinimumInIndexRange<T>(
     this T[] array, 
     int startInclusive, 
     int endExclusive 
    ) where T : IComparable { 
     Contract.Requires<ArgumentException>(ArrayAndIndexesAreValid(
      array, 
      startInclusive, 
      endExclusive) 
     ); 
     return array.Slice(startInclusive, endExclusive).Min(); 
    } 

    public static T MaximumInIndexRange<T>(
     this T[] array, 
     int startInclusive, 
     int endExclusive 
    ) where T : IComparable { 
     Contract.Requires<ArgumentException>(ArrayAndIndexesAreValid(
      array, 
      startInclusive, 
      endExclusive) 
     ); 
     return array.Slice(startInclusive, endExclusive).Max(); 
    } 
} 
+0

Das wird 'int.MaxValue' zurückgeben, wenn die Scheibe keine Elemente enthält, was wahrscheinlich keine gute Idee ist. Es mischt auch die Logik für "den minimalen Wert finden" und "eine Scheibe des Feldes betrachtend", die die LINQ-basierten Lösungen nicht tun. Wenn Sie den * maximalen * Wert eines Array-Slices finden müssen, wiederholen Sie die gesamte Slicing-Logik. –

+0

Indem Sie es nicht generisch machen, haben Sie sich auch gezwungen, es neu zu implementieren, wenn Sie den minimalen Wert von einem 'long []' usw. benötigen. Diese Operation generisch zu machen ist ein Kinderspiel IMO. Natürlich ist es schwer, dies zu tun, während Sie einen Wert für ein leeres Array-Slice zurückgeben ... –

+0

@ Jon Skeet: Es wirft auf leer (was nicht bevorzugt werden; siehe die zweite 'Contract.Requires') . Ich werde gleich auf deinen zweiten Kommentar antworten. – jason

Verwandte Themen