12
votes

LINQ A OBJETS - Retourne les paires de nombres à partir de la liste des nombres

var nums = new[]{ 1, 2, 3, 4, 5, 6, 7};
var pairs  = /* some linq magic here*/ ;
=> 
   pairs = { {1, 2}, {3, 4}, {5, 6}, {7, 0} }The elements of pairs should be either two-element lists, or instances of some anonymous class with two fields, something like new {First = 1, Second = 2}.

6 commentaires

Duplicata exact de la question posée par vous-même Stackoverflow.com/Questtions/3575925/...


@Jani non, ce n'est pas. Cela demande un équivalent à la méthode zip de Python (ou Ruby) -> prend deux listes et constitue une liste de tuples. Cette question concerne partitionnement d'une liste unique.


Une réponse très similaire - pour la fenêtre coulissante pour obtenir {{1,2}, {2,3}, {3,4}, {3,4} ... - qui devrait être facile à adapter est ici: Stackoverflow .Com / Questions / 577590 / ...


@Jani en fait, j'avais tort aussi, cette question ne concerne pas la méthode zip (), mais toujours, c'est une question différente.


@Richard qui utilise un itérateur personnalisé, pas une expression LINQ. J'admets que cela pourrait être le moyen le plus propre d'y aller.


@Cristi, enfin je monte avec la solution :-)


12 Réponses :


3
votes

Essayez ceci:

int i = 0;
var pairs = 
  nums
    .Select(n=>{Index = i++, Number=n})
    .GroupBy(n=>n.Index/2)
    .Select(g=>{First:g.First().Number, Second:g.Last().Number});


1 commentaires

Vous pouvez faire .Sélectionnez ((N, I) => ...) pour obtenir un compteur automatique



0
votes
 var nums = new float[] { 1, 2, 3, 4, 5, 6, 7 };
 var enumerable = 
        Enumerable
          .Range(0, nums.Length)
          .Where(i => i % 2 == 0)
          .Select(i => 
             new { F = nums[i], S = i == nums.Length - 1 ? 0 : nums[i + 1] });

2 commentaires

Cela reviendra des paires comme {{1,2}, {2,3}, ...}


@Lasse Cela fonctionne bien car je comprends la question, veuillez donc révoquer votre bowvote



-1
votes

Ceci donne toutes les paires possibles (VB.NET): xxx

edit: xxx

Remarque: la dernière paire est manquante, Travailler sur celui-ci

Edit:

Union UniquesPairs avec la paire {nums.Last, 0} < / p>


1 commentaires

Je n'ai pas remarqué que les paires étaient en séquence. J'ai édité la réponse



1
votes

Cela pourrait être un peu plus général que nécessaire - vous pouvez définir un élément itemsingRoup personnalisé : xxx

edit:

Si vous souhaitez ajouter des zéros (ou un autre nombre) au cas où le dernier groupe est d'une taille différente: xxx


2 commentaires

Cool! Une mise en garde, le dernier élément de paires n'aura qu'un seul élément si la liste des chiffres a un nombre impair. Par exemple. Nums = {1,2,3} => paires = {{1, 2}, {3}}


Voir la mise à jour de l'affaire Général. Si vous n'en avez besoin que de deux éléments par groupe, vous pouvez effectuer une vérification plus simple pour numount nums.count () et ajouter un 0 si c'est impair.



1
votes
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7 };
var result = numbers.Zip(numbers.Skip(1).Concat(new int[] { 0 }), (x, y) => new
        {
            First = x,
            Second = y
        }).Where((item, index) => index % 2 == 0);

2 commentaires

J'ajouterai toujours un élément dont la valeur est 0, elle sera automatiquement ignorée si la longueur des nombres est même.


Je ne savais pas qu'il y a une version où () qui prend en charge l'indexation. +1



1
votes

(AVERTISSEMENT: Ça a l'air laids)

var pairs = x.Where((i, val) => i % 2 == 1)
            .Zip(
            x.Where((i, val) => i % 2 == 0),
                (first, second) =>
                new
                {
                    First = first,
                    Second = second
                })
            .Concat(x.Count() % 2 == 1 ? new[]{
                new
                {
                    First = x.Last(),
                    Second = default(int)
                }} : null);


1 commentaires

Voler de Danny Chen, vous pouvez ajouter un élément «0» à la 2e argument de ZIP et se débarrasser ainsi de votre dernier bloc .concat (...).



0
votes
    var w =
        from ei in nums.Select((e, i) => new { e, i })
        group ei.e by ei.i / 2 into g
        select new { f = g.First(), s = g.Skip(1).FirstOrDefault() };

0 commentaires

9
votes

Aucune des méthodes de LINQ par défaut ne peut faire cela paresseusement et avec une seule analyse. Ziper la séquence avec elle-même fait 2 analyses et groupement n'est pas entièrement paresseux. Votre meilleur pari est de le mettre en œuvre directement:

public static IEnumerable<T[]> Partition<T>(this IEnumerable<T> sequence, int partitionSize) {
    Contract.Requires(sequence != null)
    Contract.Requires(partitionSize > 0)

    var buffer = new T[partitionSize];
    var n = 0;
    foreach (var item in sequence) {
        buffer[n] = item;
        n += 1;
        if (n == partitionSize) {
            yield return buffer;
            buffer = new T[partitionSize];
            n = 0;
        }
    }
    //partial leftovers
    if (n > 0) yield return buffer;
}


2 commentaires

En regardant toutes les réponses, il semble que Linq n'est pas la meilleure approche ici. Votre implémentation est assez propre.


Il devrait être statique publique iEnumerable partition ... .



1
votes
var pairs = nums.InSetsOf(2, true, 0).ToArray();

0 commentaires

1
votes
IList<int> numbers = new List<int> {1, 2, 3, 4, 5, 6, 7};
var batched = numbers.Batch(2);

0 commentaires

0
votes

Une autre option consiste à utiliser la méthode SelectMany Linq. C'est plus pour ceux qui souhaitent itérer une liste d'articles et pour chaque article de retour 2 ou plus de ses propriétés. Pas besoin de boucler à nouveau sur la liste pour chaque propriété, juste une fois. XXX


1 commentaires

Merci pour la réponse, mais cela reçoit des propriétés de chaque élément et les aplatit dans une liste unique. Ce n'est pas la question de la question initiale.



0
votes

Une autre solution simple utilisant index et index + 1 . xxx

dernier élément n'est pas valide et doit être supprimé avec Skilastn () .


0 commentaires