C# 等效于 Julia 的 map!() 方法

C# equivalent of Julia's map!() method

我正在尝试找到 C# 中与 Julia 的 map!() 方法等效的方法,该方法属于 void return 类型并采用函数、目标和函数所在的集合行为。

我能找到的最好的东西是 C# 的 Enumerable.Select(), which takes the function as the third argument, and the collection as the first argument. However, it returns a new collection instead of modifying the one in the "destination". That resembles Julia's map()

LINQ 中的所有内容均经过设计,永远不会修改基础集合并始终创建一个新的枚举,该枚举通常随后用于实例化一个新集合。

你可以像这样写一个辅助函数来实现你想要的:

public static void SelectToDestination<TSource, TResult>(
    Func<TSource, TResult> selector, 
    IEnumerable<TSource> source, 
    IList<TResult> destination)
{
    int i = 0;
    foreach (var item in source.Select(selector))
    {
        destination[i] = item;
        i++;
    }
}

用法如下:

var l1 = new List<int>() { 1, 2, 3, 4 };
var l2 = new List<int>() { 0, 0, 0, 0 };
SelectToDestination(x => x + 2, l1, l2);

foreach(var item in l2)
{
    Console.Write(item + " ");
}

结果:3 4 5 6

因为我们在方法的签名中使用了 IList<T>,目标也可以是一个数组,它会工作得很好:

public static void Main(string[] args)
{
    var l1 = new List<int>() { 1, 2, 3, 4 };
    var l2 = new int[4];
    SelectToDestination(x => x + 2, l1, l2);

    foreach(var item in l2)
    {
        Console.Write(item + " ");
    }
}

它利用了这样一个事实,即在您调用 ToArray()ToList() 之类的东西之前,LINQ 尚未实例化新集合,它只是懒惰地迭代源集合中的元素。所以不要调用 ToArray()ToList(),迭代结果 IEnumerable<TResult> 并将其分配给目标。请注意,如果您担心的话,可能有更多性能友好的方法来执行此操作。

就像 Julia 的 map 方法一样,这只有在目标集合至少一样大的情况下才有效。

没有像这样的标准,但您可以轻松地将自己的扩展方法添加到 IEnumerable 以添加此功能。例如:

public static void JuliaMap<TFrom, TTo>
(
    this IEnumerable<TFrom> source, 
    IList<TTo> target, 
    Func<TFrom, TTo> selector
)
{
    var next = 0;
    foreach(var value in source)
    {
        var convertedValue = selector(value);
        target[next] = convertedValue;
        next++;
    }
}

怎么说:

var numbers = new[]{1, 2, 3};
var target = new string[3];

numbers.JuliaMap(target, i => (i * 2).ToString());

注意:我省略了任何错误处理。例如,您需要确保目标列表足够长以获取插入的值。