3

整数の配列があり、配列内の最大数と最小数の位置を見つける必要があります。私はそれを機能させていますが、それを行うにはあまり良い方法ではないようです。私が持っているものを達成するためのより良い方法を誰かが提案できますか?

これが私のコードです:

int[] usageHours = { 3, 3, 5, 4, 0, 0, 2, 2, 4, 25, 158, 320, 212, 356, 401, 460, 480, 403, 298, 213, 102, 87, 34, 45 };
double myAverage = usageHours.Average();
int runningTotal = 0;
int runningMaxPosition = 0;

for (int i = 0; i < usageHours.Length; i++)
{
    if (usageHours[i] > runningTotal)
    {
        runningMaxPosition = i;
        runningTotal = usageHours[i];
    }
}

txtmax.Text = Convert.ToString(runningMaxPosition)+" With: "+Convert.ToString(runningTotal)+" Users";
txtAv.Text = Convert.ToString(myAverage);
4

7 に答える 7

7

そのコードはほとんど問題ありません。変数名を少し変更することをお勧めしますが、それだけです。同じループで最小値を計算できます。「if」条件をわずかに変更して、常に少なくとも 1 つの要素が選択されるようにしました (たとえば、すべての値が であってもint.MinValue)。これには他にもアプローチ方法がありますが、これは一例です。空の配列がある場合、最大 = 最小 = 0 になり、両方のインデックス = -1 になります。

int currentMax = 0;
int currentMaxIndex = -1;
int currentMin = 0;
int currentMinIndex = -1;

for (int i = 0; i < usageHours.Length; i++)
{
    if (currentMaxIndex == -1 || usageHours[i] > currentMax)
    {
        currentMaxIndex = i;
        currentMax = usageHours[i];
    }
    if (currentMinIndex == -1 || usageHours[i] < currentMin)
    {
        currentMinIndex = i;
        currentMin = usageHours[i];
    }
}

「値がありませんでした」という回答を表すために、null 許容値型を使用する別の方法を次に示します。

int currentMax? = null;
int currentMaxIndex? = null;
int currentMin? = null;
int currentMinIndex? = null;

for (int i = 0; i < usageHours.Length; i++)
{
    if (currentMax == null || usageHours[i] > currentMax.Value)
    {
        currentMax = i;
        currentMax = usageHours[i];
    }
    if (currentMin == null || usageHours[i] < currentMin.Value)
    {
        currentMinIndex = i;
        currentMin = usageHours[i];
    }
}

ただし、null 許容値型にまだ出会っていなくても心配しないでください...

于 2009-10-08T19:28:29.473 に答える
2

コードは最大値を見つけるのに問題ないようです。C# 3 以降を使用している場合は、LINQ 拡張メソッドを使用できます (メソッド、およびメソッドがありMin、さらにメソッドもあります) が、プログラミングを学んでいる印象を受けます。学習価値のためだけに、フレームワークに組み込まれる可能性のあるものを実装することをお勧めします。MaxAverageListFindIndex

于 2009-10-08T19:24:06.113 に答える
1

質問に対してワンライナーソリューションを提供したかっただけです(完全を期すために)。OPの元の質問では、彼は最大のインデックスと最小のインデックスのみを求めています。

この質問に固執しましょう。Enumerable.Max LINQ メソッドを使用するだけで最大値を見つけることができるため、これは最も興味深い質問です。同じことが Min と Average にも当てはまります。

最大のインデックスのみを提供しましょう。最小のインデックスは同様のコードで取得できます。

int indexOfMax = Enumerable.Range(0, usageHours.Length).Aggregate(
    (indexOfMax, i) => (usageHours[i] > usageHours[indexOfMax] ? i : indexOfMax)
);

Aggregate の括弧内のデリゲートは、配列のインデックスごとに実行されます。パラメータとして「これまでに見つかった最大値のインデックス」と現在のインデックスを取得します。「これまでに見つかった最大値のインデックス」を返します。明らかに、各反復で「これまでに見つかった最大値のインデックス」は、配列の対応する要素が以前の最大値より大きい場合にのみ現在のインデックスに変更されます。

于 2010-07-14T14:41:38.767 に答える
0

linq コードをスクラッチします。思い通りに動作しませんでした

コードをもう少し簡潔にすることができます

for (int i = 0; i < usageHours.Length; i++)
{
    if (usageHours[i] > usageHours[runningMaxPosition])
        runningMaxPosition = i;
}

異なるのは、一時的な runningTotal 変数を除外することだけです。

于 2009-10-08T19:23:01.793 に答える
0

これはどう:

double average = usageHours.Average();
int maxPosition = Enumerable.Range(0, usageHours.Length).Max(i => usageHours[i]);
int minPosition = Enumerable.Range(0, usageHours.Length).Min(i => usageHours[i]);
于 2009-10-08T19:25:06.063 に答える
0

Jon の回答に対するコメントで述べたように、Jon のソリューションは、実際にそれを実行するための最良の、最も直接的で、最も迅速な方法です。

ただし、Igor のソリューションを使用したい場合は、残りの部分を次に示します (実際の位置と値を取得するため)。

int maxValue = Enumerable.Range(0, usageHours.Length).Max(i => usageHours[i]);
int maxPosition = Array.FindIndex(usageHours, i => i == maxValue);
int minValue = Enumerable.Range(0, usageHours.Length).Min(i => usageHours[i]);
int minPosition = Array.FindIndex(usageHours, i => i == minValue);
于 2009-10-08T19:46:57.267 に答える
0

コードは悪くありませんが、すべての値が 0 未満の場合は機能しません。

これを試して:

int getArrayMaxPosition (double[] theArray) 
{    
    double maxVal = theArray[0];
    int ret = 0;
    int currentIndex = 0;

    foreach (double aValue in theArray) 
    {
        if (aValue > maxVal)
        {
             ret = currentIndex;
             maxVal = avalue;
        }
        currentIndex++;
    }

    return ret;
 }
于 2009-10-08T19:33:47.920 に答える