我想知道是否有內置的.NET功能來根據提供的代表的結果更改數組中的每個值。例如,如果我有一個數組{1,2,3}
和一個返回每個值的平方的委託,我希望能夠運行一個採用數組和委託的方法,並返回{1,4,9}
。這樣的事情是否已經存在?C#:改變數組中每個項目的值
回答
不,我知道(替換每個元素,而不是轉換到一個新的數組或序列),但它是非常容易寫:
public static void ConvertInPlace<T>(this IList<T> source, Func<T, T> projection)
{
for (int i = 0; i < source.Count; i++)
{
source[i] = projection(source[i]);
}
}
用途:
int[] values = { 1, 2, 3 };
values.ConvertInPlace(x => x * x);
中當然如果你真的不需要需要來改變現有的數組,那麼使用Select
發佈的其他答案會更有用。或從.NET 2現有ConvertAll
方法:
int[] values = { 1, 2, 3 };
values = Array.ConvertAll(values, x => x * x);
這是假設所有的單維數組。如果你想包含矩形數組,它會變得更加棘手,特別是如果你想避免裝箱。
+1 for ConvertAll這實際上是OP所要求的「採用數組和委託的方法,並返回...」 – 2010-10-05 21:56:40
我不明白爲什麼這會比Nathan的答案更勝於接受的答案。我錯過了什麼?選擇正是他所需要的,不是嗎? – 2010-10-07 00:44:52
@理查德:在我的回答被接受時,內森的答案可能是完整的,就多維度支持而言。我首先閱讀OP的問題的方式,我認爲他想修改陣列,只有我的答案涵蓋。對於數組到數組的轉換,'Array.ConvertAll'更高效,不需要.NET 3.5。如果只需要一個序列,那麼在我的答案中提到的「選擇」就可以了。 – 2010-10-07 06:09:46
LINQ提供了使用Select擴展方法突起支持:
var numbers = new[] {1, 2, 3};
var squares = numbers.Select(i => i*i).ToArray();
也可以使用稍微不太流利Array.ConvertAll方法:
var squares = Array.ConvertAll(numbers, i => i*i);
鐵血陣列可通過嵌套突起進行處理:
var numbers = new[] {new[] {1, 2}, new[] {3, 4}};
var squares = numbers.Select(i => i.Select(j => j*j).ToArray()).ToArray();
多維數組稍微複雜一些。我寫了下面的擴展方法,它將多維數組中的每個元素都進行投影,而不管它的級別如何。
static Array ConvertAll<TSource, TResult>(this Array source,
Converter<TSource, TResult> projection)
{
if (!typeof (TSource).IsAssignableFrom(source.GetType().GetElementType()))
{
throw new ArgumentException();
}
var dims = Enumerable.Range(0, source.Rank)
.Select(dim => new {lower = source.GetLowerBound(dim),
upper = source.GetUpperBound(dim)});
var result = Array.CreateInstance(typeof (TResult),
dims.Select(dim => 1 + dim.upper - dim.lower).ToArray(),
dims.Select(dim => dim.lower).ToArray());
var indices = dims
.Select(dim => Enumerable.Range(dim.lower, 1 + dim.upper - dim.lower))
.Aggregate(
(IEnumerable<IEnumerable<int>>) null,
(total, current) => total != null
? total.SelectMany(
item => current,
(existing, item) => existing.Concat(new[] {item}))
: current.Select(item => (IEnumerable<int>) new[] {item}))
.Select(index => index.ToArray());
foreach (var index in indices)
{
var value = (TSource) source.GetValue(index);
result.SetValue(projection(value), index);
}
return result;
}
上述方法可以與秩3的陣列進行測試如下:
var source = new int[2,3,4];
for (var i = source.GetLowerBound(0); i <= source.GetUpperBound(0); i++)
for (var j = source.GetLowerBound(1); j <= source.GetUpperBound(1); j++)
for (var k = source.GetLowerBound(2); k <= source.GetUpperBound(2); k++)
source[i, j, k] = i*100 + j*10 + k;
var result = (int[,,]) source.ConvertAll<int, int>(i => i*i);
for (var i = source.GetLowerBound(0); i <= source.GetUpperBound(0); i++)
for (var j = source.GetLowerBound(1); j <= source.GetUpperBound(1); j++)
for (var k = source.GetLowerBound(2); k <= source.GetUpperBound(2); k++)
{
var value = source[i, j, k];
Debug.Assert(result[i, j, k] == value*value);
}
您的示例應該可能使用委託而不是在lambda中指定函數,以更具體地回答問題。 – 2010-10-05 21:45:46
非常整齊。這是否考慮到多維數組? – JustOnePixel 2010-10-05 21:45:54
啊,它是。我正在尋找一個Apply方法或其他東西。永遠不會想到它被命名爲Select,但我想這與所有有趣的擴展方法的LINQ基礎一致。 – jdmichal 2010-10-05 21:46:19
使用System.Linq的你可以這樣做:
var newArray = arr.Select(x => myMethod(x)).ToArray();
LINQ查詢可以很容易地爲你解決這個問題 - 確保你引用了System.Core.dll並且有一個
using System.Linq;
聲明。例如,如果你在一個名爲numberArray變量有你的陣列,下面的代碼會給你你尋找什麼:
var squares = numberArray.Select(n => n * n).ToArray();
,如果你確實需要一個數組時,才需要最後的「ToArray的」呼叫,而不是IEnumerable <int>。
太棒了,謝謝。這是否考慮到多維數組? – JustOnePixel 2010-10-05 21:45:10
否 - 爲此,您需要一個嵌套選擇,如numberArrays.Select(as => as.Select(n => n * n).ToArray())。ToArray()。對於可讀性更高的方法,只需使用兩個嵌套循環。 – Ben 2010-10-05 21:48:20
你可以使用linq來簡化它,但要小心,不管怎樣都會發生foreach。
int[] x = {1,2,3};
x = x.Select((Y) => { return Y * Y; }).ToArray();
這裏是另一種M×N數組的解決方案,其中M和N在編譯時是未知的。
// credit: https://blogs.msdn.microsoft.com/ericlippert/2010/06/28/computing-a-cartesian-product-with-linq/
public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(IEnumerable<IEnumerable<T>> sequences)
{
IEnumerable<IEnumerable<T>> result = new[] { Enumerable.Empty<T>() };
foreach (var sequence in sequences)
{
// got a warning about different compiler behavior
// accessing sequence in a closure
var s = sequence;
result = result.SelectMany(seq => s, (seq, item) => seq.Concat<T>(new[] { item }));
}
return result;
}
public static void ConvertInPlace(this Array array, Func<object, object> projection)
{
if (array == null)
{
return;
}
// build up the range for each dimension
var dimensions = Enumerable.Range(0, array.Rank).Select(r => Enumerable.Range(0, array.GetLength(r)));
// build up a list of all possible indices
var indexes = EnumerableHelper.CartesianProduct(dimensions).ToArray();
foreach (var index in indexes)
{
var currentIndex = index.ToArray();
array.SetValue(projection(array.GetValue(currentIndex)), currentIndex);
}
}
這可能是我找到的最好的一個......並且很好,你給那個寫這個的人留下了信用(儘管問這個問題的人生氣了,但他沒有應用它) – 2016-11-16 23:38:16
- 1. 改變元組的列表中的每個項目的整數值
- 2. 更改數組中每個項目的屬性?
- 3. 從PHP數組中的每個項目創建變量
- 4. jQuery:如何爲數組中的每個項目創建變量
- 5. C#與同一陣列中的每個其他項目的數組中的每個項目
- 6. PHP數組包含每個項都是鍵和值對的數組的項目
- 7. 每個項目有2個值的數組
- 8. 取一個數組併爲每個項目添加一個值?
- 9. 用postgres乘以json數組的每個項目的值9.6
- 10. 的Javascript:對象的數組,每個對象改變值異步
- 11. JQuery的數組值附加到每個項目
- 12. C#JSON到每個項目
- 13. SVN項目組織:每個模塊或每個項目
- 14. C#更改現有列表框項目中變量的值
- 15. 製作組合列表中的每個項目的項目
- 16. 數組變量中的項目總數
- 17. 如何阻止str_replace更改數組中每個項目中的所有實例?
- 18. 如何獲取多維數組中每個項目的第一個值?
- 19. SQL:選擇每個組獨特的最小值和改變值
- 20. 改變函數中的數組c
- 21. Java:無法繪製()從一個數組中的每個項目
- 22. Nativescript listview每個項目中的多個數組
- 23. 獲取數組中的每個第n個項目
- 24. 如何統計數組中每個項目的出現次數?
- 25. iOS - 防止更改一個數組中的項目影響其他 - 目標C
- 26. 經歷每個所選的項目,*改變*的ListView
- 27. 如何組數組項通過彙總每個項目
- 28. 每個數組值
- 29. 改變多個項目的CSS:目標
- 30. 在單行中打印arraylist中的每個數組項目
傳統上,這將被稱爲地圖;在Linq中它被稱爲Select。 – 2010-10-06 00:28:17