だから私はソートされていない数値配列を持っていてint[] anArray = { 1, 5, 2, 7 };
、値と7と3になる配列の最大値のインデックスの両方を取得する必要がありますか?
だから私はソートされていない数値配列を持っていてint[] anArray = { 1, 5, 2, 7 };
、値と7と3になる配列の最大値のインデックスの両方を取得する必要がありますか?
回答:
これは最も魅力的な方法ではありませんが、機能します。
(持っている必要がありますusing System.Linq;
)
int maxValue = anArray.Max();
int maxIndex = anArray.ToList().IndexOf(maxValue);
.ToList()
配列も明示的に実装する必要はありませんIList
IList
インターフェイスをますが、明示的にます:msdn.microsoft.com/en-us/library/…。(配列には、対応する汎用IList<T>
インターフェイスも実装されています。)
ToList()
は常にコピーすることです。メソッドをコピーすることもコピーしないことも、ひどい考えです。これは、かなりクレイジーなエイリアシングバグにつながります。実際の実装はToList()
多かれ少なかれreturn new List(source)
インデックスがソートされていない場合は、少なくとも1回配列を反復処理して、最大値を見つける必要があります。シンプルなfor
ループをます。
int? maxVal = null; //nullable so this works even if you have all super-low negatives
int index = -1;
for (int i = 0; i < anArray.Length; i++)
{
int thisNum = anArray[i];
if (!maxVal.HasValue || thisNum > maxVal.Value)
{
maxVal = thisNum;
index = i;
}
}
これは、LINQや他の1行のソリューションを使用するものよりも詳細ですが、おそらく少し高速です。これをO(N)より速くする方法は本当にありません。
maxVal
インデックス0の配列値に初期化し(配列の長さが1であると想定)、0に初期化してindex
、forループをで開始することにより、1回の反復を保存できますi = 1
。
必須のLINQ one [1]-ライナー:
var max = anArray.Select((value, index) => new {value, index})
.OrderByDescending(vi => vi.value)
.First();
(ソートはおそらく他のソリューションよりもパフォーマンスに影響を与えます。)
[1]:与えられた値「1」の場合。
簡潔なワンライナー:
var max = anArray.Select((n, i) => (Number: n, Index: i)).Max();
テストケース:
var anArray = new int[] { 1, 5, 2, 7 };
var max = anArray.Select((n, i) => (Number: n, Index: i)).Max();
Console.WriteLine($"Maximum number = {max.Number}, on index {max.Index}.");
// Maximum number = 7, on index 4.
特徴:
備考:
anArray.Select((n, i) => ( Index: i, Number: n)).Max()
比較方法のために、最大数ではなく最大インデックスを見つけます(item1が最も重要など)
ここに2つのアプローチがあります。配列が空の場合の処理を追加することもできます。
public static void FindMax()
{
// Advantages:
// * Functional approach
// * Compact code
// Cons:
// * We are indexing into the array twice at each step
// * The Range and IEnumerable add a bit of overhead
// * Many people will find this code harder to understand
int[] array = { 1, 5, 2, 7 };
int maxIndex = Enumerable.Range(0, array.Length).Aggregate((max, i) => array[max] > array[i] ? max : i);
int maxInt = array[maxIndex];
Console.WriteLine($"Maximum int {maxInt} is found at index {maxIndex}");
}
public static void FindMax2()
{
// Advantages:
// * Near-optimal performance
int[] array = { 1, 5, 2, 7 };
int maxIndex = -1;
int maxInt = Int32.MinValue;
// Modern C# compilers optimize the case where we put array.Length in the condition
for (int i = 0; i < array.Length; i++)
{
int value = array[i];
if (value > maxInt)
{
maxInt = value;
maxIndex = i;
}
}
Console.WriteLine($"Maximum int {maxInt} is found at index {maxIndex}");
}
以下のコードの出力:
00:00:00.3279270-max1 00:00:00.2615935-max2 00:00:00.6010360-max3(arr.Max())
配列の100000000 intの場合、それほど大きな違いはありませんが、それでも...
class Program
{
static void Main(string[] args)
{
int[] arr = new int[100000000];
Random randNum = new Random();
for (int i = 0; i < arr.Length; i++)
{
arr[i] = randNum.Next(-100000000, 100000000);
}
Stopwatch stopwatch1 = new Stopwatch();
Stopwatch stopwatch2 = new Stopwatch();
Stopwatch stopwatch3 = new Stopwatch();
stopwatch1.Start();
var max = GetMaxFullIterate(arr);
Debug.WriteLine( stopwatch1.Elapsed.ToString());
stopwatch2.Start();
var max2 = GetMaxPartialIterate(arr);
Debug.WriteLine( stopwatch2.Elapsed.ToString());
stopwatch3.Start();
var max3 = arr.Max();
Debug.WriteLine(stopwatch3.Elapsed.ToString());
}
private static int GetMaxPartialIterate(int[] arr)
{
var max = arr[0];
var idx = 0;
for (int i = arr.Length / 2; i < arr.Length; i++)
{
if (arr[i] > max)
{
max = arr[i];
}
if (arr[idx] > max)
{
max = arr[idx];
}
idx++;
}
return max;
}
private static int GetMaxFullIterate(int[] arr)
{
var max = arr[0];
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] > max)
{
max = arr[i];
}
}
return max;
}
public static class ArrayExtensions
{
public static int MaxIndexOf<T>(this T[] input)
{
var max = input.Max();
int index = Array.IndexOf(input, max);
return index;
}
}
これはすべての変数タイプで機能します...
var array = new int[]{1, 2, 4, 10, 0, 2};
var index = array.MaxIndexOf();
var array = new double[]{1.0, 2.0, 4.0, 10.0, 0.0, 2.0};
var index = array.MaxIndexOf();
public static void Main()
{
int a,b=0;
int []arr={1, 2, 2, 3, 3, 4, 5, 6, 5, 7, 7, 7, 100, 8, 1};
for(int i=arr.Length-1 ; i>-1 ; i--)
{
a = arr[i];
if(a > b)
{
b=a;
}
}
Console.WriteLine(b);
}
以下は、適切な定数係数を持つO(n)であるLINQソリューションです。
int[] anArray = { 1, 5, 2, 7, 1 };
int index = 0;
int maxIndex = 0;
var max = anArray.Aggregate(
(oldMax, element) => {
++index;
if (element <= oldMax)
return oldMax;
maxIndex = index;
return element;
}
);
Console.WriteLine("max = {0}, maxIndex = {1}", max, maxIndex);
ただしfor
、パフォーマンスを重視する場合は、明示的なlop を実際に作成する必要があります。
を使用してちょうど別の視点DataTable
。andとDataTable
呼ばれる2つの列を持つa を宣言します。オプションとその両方および値を列に追加します。次に、ループを使用して、各配列項目を行として挿入します。次に、メソッドを使用して、最大値を持つ行を選択します。index
val
AutoIncrement
AutoIncrementSeed
AutoIncrementStep
1
index
foreach
datatable
Select
コード
int[] anArray = { 1, 5, 2, 7 };
DataTable dt = new DataTable();
dt.Columns.AddRange(new DataColumn[2] { new DataColumn("index"), new DataColumn("val")});
dt.Columns["index"].AutoIncrement = true;
dt.Columns["index"].AutoIncrementSeed = 1;
dt.Columns["index"].AutoIncrementStep = 1;
foreach(int i in anArray)
dt.Rows.Add(null, i);
DataRow[] dr = dt.Select("[val] = MAX([val])");
Console.WriteLine("Max Value = {0}, Index = {1}", dr[0][1], dr[0][0]);
出力
Max Value = 7, Index = 4
配列内の最大数と最小数を見つけます。
int[] arr = new int[] {35,28,20,89,63,45,12};
int big = 0;
int little = 0;
for (int i = 0; i < arr.Length; i++)
{
Console.WriteLine(arr[i]);
if (arr[i] > arr[0])
{
big = arr[i];
}
else
{
little = arr[i];
}
}
Console.WriteLine("most big number inside of array is " + big);
Console.WriteLine("most little number inside of array is " + little);
以下を検討してください。
/// <summary>
/// Returns max value
/// </summary>
/// <param name="arr">array to search in</param>
/// <param name="index">index of the max value</param>
/// <returns>max value</returns>
public static int MaxAt(int[] arr, out int index)
{
index = -1;
int max = Int32.MinValue;
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] > max)
{
max = arr[i];
index = i;
}
}
return max;
}
使用法:
int m, at;
m = MaxAt(new int[]{1,2,7,3,4,5,6}, out at);
Console.WriteLine("Max: {0}, found at: {1}", m, at);
これはfor
、ゴルフに向かっている場合、ボディレスループで実行できます;)
//a is the array
int mi = a.Length - 1;
for (int i=-1; ++i<a.Length-1; mi=a[mi]<a[i]?i:mi) ;
のチェックで++i<a.Length-1
は、最後のインデックスのチェックが省略されます。最大インデックスが最初の最後のインデックスであるかのように設定した場合、これは問題になりません。他の要素に対してループが実行されると、ループは終了し、いずれかがtrueになります。
mi
mi
、と私たちは初期で立ち往生mi
実際の作業は、ポストループ修飾子によって行われます。
a[mi]
つまり、でインデックス付けされた配列mi
)は、現在のアイテムよりも小さいですか?
mi
覚えて新しいものを保存しますi
。mi
ない(何もしない)操作の最後に、最大値が見つかるインデックスがあります。論理的には、最大値はa[mi]
配列があり、最大値のインデックス、最大値の実際の値がわかっている場合、「最大値と最大値のインデックス」が最大値を追跡するために実際にどのように必要なのか、私にはよくわかりませんでした。インデックスを使用して配列にインデックスを付ける簡単なケースです。