我想知道是否有内置的.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. 的Javascript:对象的数组,每个对象改变值异步
- 4. 用postgres乘以json数组的每个项目的值9.6
- 5. JQuery的数组值附加到每个项目
- 6. SVN项目组织:每个模块或每个项目
- 7. C#更改现有列表框项目中变量的值
- 8. 数组变量中的项目总数
- 9. 制作组合列表中的每个项目的项目
- 10. 如何获取多维数组中每个项目的第一个值?
- 11. 获取数组中的每个第n个项目
- 12. Nativescript listview每个项目中的多个数组
- 13. 如何统计数组中每个项目的出现次数?
- 14. 经历每个所选的项目,*改变*的ListView
- 15. 每个数组值
- 16. 如何组数组项通过汇总每个项目
- 17. 在单行中打印arraylist中的每个数组项目
- 18. 在C++中改变函数内部二维数组的值
- 19. jQuery改变每个第四项的CSS?
- 20. PHP是变量中的数组项目
- 21. php更改二维数组中的项目的值
- 22. 获取值了一个数组,并为每个值的变量
- 23. 每个用于Drupal数组中的项目的PHP
- 24. 数组排序,其中每个项目是一个逗号分隔在vb.net值
- 25. 使用变量的值查找数组中的项目
- 26. UITableView中的SimpleDB项目,属性和值的可变数组
- 27. C# - 改变组合框项目的索引?
- 28. 在JavaScript中获取数组中的每个变量循环值
- 29. PHP:如何从数组中只打印一次每个项目的值?
- 30. React Native JS多个项目每个数组条目
传统上,这将被称为地图;在Linq中它被称为Select。 – 2010-10-06 00:28:17