2
votes

C # Linq comment comparer deux chaînes et rapporter le premier caractère différent qui est lui-même différent de '?' joker

J'ai une fonction qui compare deux chaînes et rapporte le premier caractère différent:

int index = str1.Zip(str2, (c1, c2) => c1 == c2).TakeWhile(b => b).Count();

donc toute la magie est là:

public static int Diff(this string str1, string str2)
{
    try
    {
        if (str1 == null || str2 == null)
            return 0;
        int index = str1.Zip(str2, (c1, c2) => c1 == c2).TakeWhile(b => b).Count();
        return index;
    }
    catch (Exception)
    {
        return 0;
    }

}

disons que nous avons deux chaînes:

ENTRÉE, 1,1,0,0,0,0,0,0,0,0,0,0

INPUT,?,?, 1,?,?,?,?,?,?,?,?,?

01234567890

Donc, compte tenu de tous les caractères, le premier différent est-il? donc la réponse est 6 (à partir de 0). Cela fonctionne correctement.

Maintenant, je voudrais vous présenter? comme un caractère générique qui doit donc être ignoré et donc la réponse devrait être 10 (à partir de 0).

Je ne sais pas comment changer le code ci-dessus dans l'expression linq pour faire cela . J'ai essayé int index = str1.Zip (str2, (c1, c2) => c1 == c2 && c2! = '?'). TakeWhile (b => b) .Count (); mais cela ne change rien et rapporte toujours 6 au lieu de 9.

Je voudrais m'en tenir à linq au lieu de passer par une boucle for (plus facile) Merci


1 commentaires

c1 == c2 || c2 == '?'


4 Réponses :


1
votes

Je pense que vous avez juste besoin de changer légèrement la condition logique.

Si la condition utilisée dans le Zip est toujours fausse, nous arrêtons d'y chercher. Nous ne devrions cesser de chercher que lorsque les deux caractères ne sont pas identiques et l’un d’eux n’est pas un joker.

La condition doit donc être:

index = str1.Zip(str2, (c1, c2) => c1 == c2 || c1 != '?' || c2 != '?').TakeWhile(b => b).Count();

Évidemment, cela pourrait être simplifié en utilisant les lois de DeMorgan:

c1 == c2 || c1 != '?' || c2 != '?'

Par conséquent, la ligne devient:

!(c1 != c2 && (c1 != '?' || c2 != '?'))


0 commentaires

3
votes

Vous avez besoin du caractère générique pour être considéré comme une condition supplémentaire possible true . Par conséquent, vous devez utiliser OR || au lieu de AND && :

Pas:

int index = str1.Zip (str2, (c1, c2) => c1 == c2 && c2! = '?'). TakeWhile (b => b) .Count ();

À la place:

int index = str1.Zip (str2, (c1, c2) => c1 == c2 || c2 == '?'). TakeWhile (b => b) .Count ();

Vous pouvez ajouter un || supplémentaire à l'expression si vous souhaitez également ignorer les caractères génériques dans la première entrée.


0 commentaires

1
votes

en utilisant linq, Fiddle ici .

var index = c1.Zip(c2, (a, b) => new { a, b })
            .Select((p, i) => new { p.a, p.b, i })
            .Where(p => p.b != wildcard)
            .FirstOrDefault(p => p.a != p.b)?.i;


0 commentaires

1
votes

Voici la solution entièrement testée:

            string input1 = "1,1,0,0,0,0,0,0,0,0,0,0";
            string input2 = "\u003F,\u003F,1,\u003F,\u003F,\u003F,\u003F,\u003F,\u003F,\u003F,\u003F,\u003F";

            int results = input1.Select((x, i) => new { chr = x, index = i }).Where(x => (x.chr != input2[x.index]) && (x.chr != '\u003F') && (input2[x.index] != '\u003F')).Min(x => x.index);


0 commentaires