1
votes

F # Array.choose id équivalent en C #

J'adore utiliser Array.choose id en F # sur Option []. Quelle est la meilleure façon de procéder en C # pour Nullable []?

--- Modifié pour répondre aux excellents commentaires ---
En F #, j'utilise Array.choose id pour filtrer None : Option <'T> [] ->' T [] . < br> Quel est le bon moyen de filtrer null en C # avec Linq: Nullable [] => T [] ?


2 commentaires

vous voudrez peut-être simplement demander l'équivalent et supprimer la «meilleure» partie. Les questions demandant la «meilleure» façon de faire quelque chose ont tendance à être signalées comme étant basées sur des opinions.


Est-ce que items.Where (x => x! = Null) va bien? Cherchez-vous simplement à obtenir les éléments qui ne sont pas nuls, ou à passer également de Nullable [] à simplement T [] ?


3 Réponses :


4
votes

Je le traduirais en C #

int?[] all = new int?[3] { 10, null, 100 };
int[] chosen = all
    .Where(e => e.HasValue)
    .Select(e => e.Value)
    .ToArray();

Vous pouvez omettre ToArray () si vous voulez juste être comme un IEnumerable, et .Select (..) si vous ne voulez pas que les nullables soient décompressés


1 commentaires

J'avais ceci sauf .Where (e => e! = Null) . Très beau!



2
votes

Vous pouvez utiliser SelectMany avec une autre fonction pour convertir un T? en un IEnumerable :

var nullables = new int?[] { null, 1, 4, null, 3, null, 29 };
int[] values = nullables.SelectMany(ni => ni.ToSeq()).ToArray();


3 commentaires

C'est intelligent, mais cela implique énormément d'appels à GetEnumerator / MoveNext / Current, puisque vous créez un IEnumerable par valeur dans le tableau d'origine. Je soupçonne que l'approche Where / Select fonctionne mieux lorsque le tableau est grand.


Je me suis posé des questions à ce sujet. En revanche, cette version est plus sûre que le Where / Select (si la commande est inversée => NRE). Si les types de référence Nullable C # 8 sont activés, le lambda dans Select devient e => e! .Value , ce qui semble inutilement dangereux.


@BrettRowberry Eh bien, le ! pour indiquer "Je sais que ce n'est pas nul même si le système de types le dit" est exactement fait pour des situations comme celle où vous venez de vérifier HasValue et vous le savez avec certitude ce n'est pas nul. Cela ne me semble pas dangereux du tout, c'est à ça que ça sert.



0
votes

Si vous êtes fan de l'option F #, vous aimerez peut-être la bibliothèque facultative en C # .

Dans tous les cas, j'aime utiliser une méthode d'extension pour cela. Je l'utilise avec cette bibliothèque facultative, mais voici une version Nullable. Cette version est limitée à la sortie des types de valeur, mais la version Option peut également gérer les types de référence.

/// <summary>
///     Allows you to map and filter in a single operation, by passing in a function that returns
///     a Nullable containing the output that should be included in the final result.
///     Only the values that are not null are included in the resulting sequence.
/// </summary>
public static IEnumerable<T2> Choose<T1, T2>(this IEnumerable<T1> enumerable, Func<T1, T2?> selector) where T2 : struct
{
    if (enumerable is null) throw new ArgumentNullException(nameof(enumerable));
    if (selector is null) throw new ArgumentNullException(nameof(selector));

    // The nested function ensures argument validation happens immediately, rather than
    // being delayed until the caller starts iterating the results.

    IEnumerable<T2> iterator()
    {
        foreach (var item in enumerable)
        {
            var output = selector(item);
            if (output.HasValue)
                yield return output.Value;
        }
    }

    return iterator();
}


2 commentaires

Le type Option de F # est également disponible en C # ... Sans ce package tiers


@MalteR C'est vrai, mais la bibliothèque facultative est mieux adaptée à une utilisation dans un langage qui manque d'expressions match . Il a une méthode Match à laquelle vous passez des expressions lambda qui gèrent le cas Some et None. Donc, contrairement à l'utilisation de l'option F # de C #, vous ne pouvez pas accéder à la valeur de l'option sauf si vous vérifiez d'abord certains / aucun.