2010-07-26 11 views
2

Ceci est lié à Another Question, ce que je pense vraiment à un problème beaucoup plus simple, donc je pose la question plus simple ici dans l'espoir que cela m'aidera à résoudre le plus complexe. Je souhaiterais pouvoir créer un regroupement dans une requête linq to sql qui se base sur une plage de données dans un autre ensemble de données. Cependant, je pense que cela devrait fonctionner aussi bien dans linq pour les objets, alors allons-y avec ça.Pouvez-vous créer un regroupement en fonction des plages?

Imaginez que vous avez deux listes contenant des valeurs

{100, 110, 120, 130, 140, 150, 160, 170} 
{115, 145, 180} 

Maintenant, je voudrais groupe la première liste par la seconde sous forme de fourchettes (valeurs qui sont entre chaque groupe). C'est, je voudrais un groupement comme celui-ci (le 0 est implicite):

{0} {100, 110} 
{115} {120, 130, 140} 
{145} {150, 160, 170} 
{180} 

Je suis presque certain que je suis abusant de la terminologie, et probablement une mauvaise compréhension de la façon dont le groupe LINQ par les œuvres de l'opérateur, mais si vous obtenez ce que je veux dire, j'aimerais des suggestions. Merci.

Répondre

2

Eh bien, vous pouvez certainement exprimer dans LINQ facilement:

var x = from value in values 
     group value by ranges.Where(x => value >= x) 
          .DefaultIfEmpty() 
          .Last(); 

Mais je doute fort que cela fonctionnera dans LINQ to SQL. Fondamentalement, vous devez trouver un moyen simple de mapper une valeur à l'une de ces catégories.

Exemple complet:

using System; 
using System.Linq; 
using System.Collections.Generic; 

class Test 
{ 
    static void Main() 
    { 
     int[] values = {100, 110, 120, 130, 140, 150, 160, 170}; 
     int[] ranges = {115, 145, 180}; 

     var query = from value in values 
        group value by ranges.Where(x => value >= x) 
             .DefaultIfEmpty() 
             .Last(); 

     foreach (var group in query) 
     { 
      Console.WriteLine("{0}: {{{1}}}", group.Key, 
           string.Join(", ", group)); 
     } 
    } 
} 

Sortie:.

0: {100, 110} 
115: {120, 130, 140} 
145: {150, 160, 170} 

Notez que ce ne sera pas inclure toutes les catégories qui n'ont pas de valeurs dans

Notez également que ce serait plus simple (en utilisant First() au lieu de Last()) si vous seriez heureux de classer légèrement différemment:

115: {100, 110} 
145: {120, 130, 140} 
180: {150, 160, 170} 

En d'autres termes, si la catégorie a été définie par la première valeur de gamme ultérieure à la valeur de ligne.

EDIT: Voici une version qui donne les groupes vides. C'est assez horrible cependant, IMO:

var query = from range in ranges 
      join value in values 
      on range equals ranges.Where(x => value >= x) 
            .DefaultIfEmpty() 
            .Last() into groups 
      select new { Key = range, Values = groups}; 

foreach (var group in query) 
{ 
    Console.WriteLine("{0}: {{{1}}}", group.Key, 
         string.Join(", ", group.Values)); 
} 
+0

J'ai besoin des catégories sans valeurs aussi, mais peut-être que je peux comprendre quelque chose là-bas. Vos connaissances sur ces sujets ne cessent jamais de m'étonner;) –

+0

Ne pouvez-vous pas faire une jointure externe pour obtenir les catégories inutilisées? – Gabe

+0

@Gabe: Les jointures externes ne sont pas faciles dans LINQ. Il est possible qu'une réunion de groupe fonctionne, mais c'est un peu pénible ... Je regarde maintenant. –