Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Abonnements

Quizz 6

L'idée ici est de partir d'un IEnumerable<IEnumerable<T>> et de récupérer le début commun à tous les sous-IEnumerable :

class Program

{

    static void Main(string[] args)

    {

        int[][] values = { new int[] { 1, 2, 3, 4, 5 }, new int[] { 1, 2, 3, 6, 7 }, new int[] { 1, 2, 8, 9 } };

        foreach (int v in CommonBegining(values))

            Console.WriteLine(v);

        Console.WriteLine();

        int[][] values2 = {new int[]{ 1, 2, 3, 4, 5 }, new int[]{1, 2, 3, 6, 7}, new int[]{1}};

        foreach (int v in  CommonBegining(values2))

            Console.WriteLine(v);

    }

 

    static IEnumerable<int> CommonBegining(IEnumerable<IEnumerable<int>> values)

    {

        // Just code it!

    }

}

devra afficher :

1
2

1

En effet, dans le premier cas, on a {1, 2, 3, 4, 5},  {1, 2, 3, 6, 7} et {1, 2, 8, 9}

Dans le deuxième cas, on a {1, 2, 3, 4, 5}, {1, 2, 3, 6, 7} et {1}.

Inutile de préciser, il faut faire ça en C#3.

Enjoy Smile

Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :

Publié mardi 12 août 2008 13:06 par Matthieu MEZIL

Classé sous : , , ,

Commentaires

# re: Quizz 6 @ mardi 12 août 2008 16:55

C'est du VB8 (même pas 9) mais cela devrait marcher.

CommonBegining = new List(Of Integer)

Dim Enumerators as new List(Of Enumerator)

For Each E as Enumerable(Of Integer) in values

....Enumerators.Add(E)

Next

If Enumerators.Count = 0 Then Exit Function

Dim Current as Integer = 0

Do

....For X as Integer = 1 to Enumerators.Count-1

........If Not Enumerators(X).Next() OrElse Enumerators(X).Current <> Current Then Exit Function

....Next

....CommonBegining.Add(Current)

Loop While Enumerators(0).Next()

FREMYCOMPANY

# re: Quizz 6 @ mardi 12 août 2008 17:02

ARGGGGGGGGGGGGGGGGGGGGGG du VB quel horreur. LOL. Plus sérieusement, c'est pas le but. Si tu veux le faire en VB, fais le en VB9 en utilisant que les nouveautés de VB9. Même si c'est moins performant dans certains cas, le but ici est de se faire plaisir entre geek en utilisant les dernières features.

Pour ma part, je le fais en une seule instruction grâce aux nouveautés de C#3/VB9 et ça c'est la classe Wink

Matthieu MEZIL

# re: Quizz 6 @ mardi 12 août 2008 17:13

Voilà qui m'apprendra à poster sans tester...

   Function CommonBegining(ByVal values As IEnumerable(Of IEnumerable(Of int))) As IEnumerable(Of int)

       CommonBegining = New List(Of Integer)

       Dim Enumerators As New List(Of IEnumerator)

       For Each E As IEnumerable(Of Integer) In values

           Enumerators.Add(E.GetEnumerator())

       Next

       If Enumerators.Count = 0 Then Exit Function

       If Enumerators.Count = 1 Then

           CType(CommonBegining, List(Of int)).AddRange(values(0))

           Exit Function

       End If

       Dim Current As Integer = 0

       Do While Enumerators(0).MoveNext()

           Current = Enumerators(0).Current

           For X As Integer = 1 To Enumerators.Count - 1

               If Not Enumerators(X).MoveNext() OrElse Enumerators(X).Current <> Current Then Exit Function

           Next

           CType(CommonBegining, List(Of int)).Add(Current)

       Loop

   End Function

FREMYCOMPANY

# re: Quizz 6 @ mardi 12 août 2008 17:23

@Matthieu : Oui, je m'en doutais (j'avais déjà vu les précédents quizz) mais j'avais envie de partager ma solution personnelle, même si je ne l'ai pas fait en LINQ. Après tout, le bug est de trouver une solution, pourquoi forcer les participants à trouver une en LINQ Wink

Ma solution n'empechera pas les autres de trouver leur propre solution en LINQ to Objets, si ils le veulent.

FREMYCOMPANY

# re: Quizz 6 @ mardi 12 août 2008 17:32

@Fremy : C'est pas faux. On peut d'ailleurs remarquer à quel point c'est chiant de pas avoir le yield return en VB. hi hi hi Stick out tongue

Par contre le coup du Exit Function et de jamais faire de Return je trouve ça super moche. Autant un Exit Sub j'accepte, autant un Exit Function je trouve que c'est une hérésie. Ick!

Matthieu MEZIL

# re: Quizz 6 @ mardi 12 août 2008 17:38

J'ai pas de VS sous la main donc je peux pas tester mais je verrais bien l'utilisation de la méthode d'extension Interect ou un truc du genre non ?

Thomas LEBRUN

# re: Quizz 6 @ mardi 12 août 2008 17:38

Pitié les CSharpers, proposez moi une solution avec du bon C#3 histoire de me redonner un peu de beaume au coeur Wink

Matthieu MEZIL

# re: Quizz 6 @ mardi 12 août 2008 18:04

@ Thomas : Je vois pas bien comment mais je demande qu'à avoir tord. En effet, Intesect marche très bien dans le cas de mon premier quizz mais dans le cas où ce que l'on cherche c'est le début commun, je ne vois pas comment l'utiliser.

Cependant, si tu y arrives, je suis preneur.

Matthieu MEZIL

# re: Quizz 6 @ mardi 12 août 2008 20:24

Bon, c'est pas du C#3, mais je suis intéressé par le résultat en C#3...

Pour me faire pardonner, j'ai fait une belle méthode d'extension réutilisable. En revanche, je ne vois pas de moyen d'éviter au moins une allocation.

   public static class Extensions

   {

       private static IEnumerable<IEnumerator<T>> GetEnumerators<T>(IEnumerable<IEnumerable<T>> values)

       {

           if (values == null)

               yield break;

           foreach (IEnumerable<T> e in values)

           {

               if (e == null)

                   yield break;

               yield return e.GetEnumerator();

           }

       }

       public static IEnumerable<T> CommonFirst<T>(this IEnumerable<IEnumerable<T>> values) where T: struct

       {

           return CommonFirst(GetEnumerators(values));

       }

       public static IEnumerable<T> CommonFirst<T>(this IEnumerable<IEnumerator<T>> enumerators) where T: struct

       {

           if (enumerators == null)

               yield break;

           IEnumerable<IEnumerator<T>> enumeratorsCopy = enumerators.ToArray();

           do

           {

               T? current = null;

               foreach (IEnumerator<T> e in enumeratorsCopy)

               {

                   if (!e.MoveNext())

                       yield break;

                   if (current == null)

                   {

                       current = e.Current;

                   }

                   else

                   {

                       if (!EqualityComparer<T>.Default.Equals(current.Value, e.Current))

                           yield break;

                   }

               }

               if (current == null)

                   yield break;

               yield return current.Value;

           }

           while (true);

       }

   }

smo

# re: Quizz 6 @ mercredi 13 août 2008 04:23

Je crois bien que je l'ai Wink

       static IEnumerable<int> CommonBegining(IEnumerable<IEnumerable><int>&gt; values)

       {

           if (values != null && values.Any() && values.First() != null)

               return values.First().TakeWhile((v, i) => values.Skip(1).All(v2 => v2.ElementAt(i) == v));

           return new int[0];

       }

Adrien Siffermann

# re: Quizz 6 @ mercredi 13 août 2008 04:30

Oups, par contre on dirait que mon commentaire a mal vécu le formatage...

Désolé... Smile

Adrien Siffermann

# re: Quizz 6 @ mercredi 13 août 2008 08:30

chez moi, ça plante sur ElementAt, en le modifiant en ElementAtOrDefault, ça passe.

PS: Pour information, cette méthode est environ 100 fois moins rapide que ma proposition! Je sais que ce n'est qu'un quizz :), mais tout de même... n'est on pas capable d'aller aussi vite avec ces méthodes?

smo

# re: Quizz 6 @ mercredi 13 août 2008 09:50

@ Adrien : Pour ce qui est des commentaires c'est toujours comme ça mais je remet en forme derrière. Pour ta réponse, c'est pas mal du tout mais comme le présice Simon ta méthode génère une exception.

@Simon : Non ElementAtOrDefault n'est pas non plus la bonne méthode. Le default(int) c'est 0 donc dans le cas suivant :

{ { 1, 0 }, { 1, 0 }, { 1 } }

on va récupérer {1, 0} au lieu de 1.

La solution que je propose est la suivante :

values.Aggregate((v1, v2) => v1.TakeWhile((v, index) => v2.Count() > index && v == v2.ElementAt(index)));

Matthieu MEZIL

# re: Quizz 6 @ mercredi 13 août 2008 10:22

ah ok pour le ElementAtOrDefaut, c'était surtout pour me permettre de compiler et tester :-)

Sais tu écrire ceci avec la vraie syntaxe LINQ (select from), sans les méthodes . ?

PS: pour info, c'est encore 20 fois moins rapide que ma proposition. Ca fait tout de même une perte de 2000% de performance, sachant que je ne suis pas sûr que tu gères tous les cas (null, ...)

smo

# re: Quizz 6 @ mercredi 13 août 2008 10:33

Effectivement je ne gère pas le null.
Pour le gérer, on pourrait faire ça :

values == null || values.Any(v => v == null) ? Enumerable.Empty<int>() : values.Aggregate((v1, v2) => v1.TakeWhile((v, index) => v2.Count() > index && v == v2.ElementAt(index)));

Pour ce qui est de l'écrire en LINQ, ce n'est pas que je ne sais pas, c'est que ce n'est pas possible. LINQ n'est pas prévu pour ça (au moins pour la version actuelle).

Pour ce qui est des perfs, je les améliore un peu avec le Quizz 7.

Matthieu MEZIL

# re: Quizz 6 @ mercredi 13 août 2008 11:38

20 fois moins rapide !!! Je ne sais pas comment tu as fait tes tests mais moi j'obtiens 2 fois moins rapide.

Pour le Quizz7, je suis 1,5 fois moins rapide MAIS pour le quizz 8, je suis 1,5 fois PLUS rapide !!!

Matthieu MEZIL

# re: Quizz 6 @ mercredi 13 août 2008 12:23

@Matthieu : Effectivement, y'a pas de yield en VB, c'est pour ca que j'utilise "Exit Function". Je ne l'utilise que pour simuler le "yield" de C#, sinon je préfère return.

FREMYCOMPANY

# re: Quizz 6 @ mercredi 13 août 2008 17:36

Allez, patience, à priori VB10 devrait permettre le yield return.

Matthieu MEZIL

Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Merci par Blog de Jérémy Jeanson le 10-01-2019, 20:47

- Office 365: Script PowerShell pour auditer l’usage des Office Groups de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 11:02

- Office 365: Script PowerShell pour auditer l’usage de Microsoft Teams de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 10:39

- Office 365: Script PowerShell pour auditer l’usage de OneDrive for Business de votre tenant par Blog Technique de Romelard Fabrice le 04-25-2019, 15:13

- Office 365: Script PowerShell pour auditer l’usage de SharePoint Online de votre tenant par Blog Technique de Romelard Fabrice le 02-27-2019, 13:39

- Office 365: Script PowerShell pour auditer l’usage d’Exchange Online de votre tenant par Blog Technique de Romelard Fabrice le 02-25-2019, 15:07

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Stream Portal par Blog Technique de Romelard Fabrice le 02-21-2019, 17:56

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Video Portal par Blog Technique de Romelard Fabrice le 02-18-2019, 18:56

- Office 365: Script PowerShell pour extraire les Audit Log basés sur des filtres fournis par Blog Technique de Romelard Fabrice le 01-28-2019, 16:13

- SharePoint Online: Script PowerShell pour désactiver l’Option IRM des sites SPO non autorisés par Blog Technique de Romelard Fabrice le 12-14-2018, 13:01