2017-10-21 103 views
-1

J'ai une requête LINQ qui fonctionne au singulier - ici il est:Linq choisir entre 2 valeurs pour une liste d'id

public static AmountRange GetAmountRange(int term) 
{ 
    return amountTable 
     .Where(x => term.IsBetween(x.MinTerm, x.MaxTerm)) 
     .Select(x => new AmountRange(term, x.MinAmount, x.MaxAmount)) 
     .First(); 
} 

La fonction IsBetween est une méthode simple d'extension « int », qui fait exactement ce que ça dit. Ce que je voudrais faire est de faire une autre variante qui accepte un tableau de 'int []' comme paramètre initial afin que je n'appelle pas plusieurs fois la requête.

S'il s'agissait d'un tableau de valeurs uniques, j'utiliserais simplement la fonctionnalité .Contains, mais ce n'est pas le cas.

Voici un exemple qui utilise .Contains - cependant, il ne permet pas une plage - seulement une seule valeur. Il doit être converti de sorte que chaque terme IsBetween MinAmount et MaxAmount.

public static IEnumerable<AmountRange> SelectAmountRange(int[] terms) 
{ 
    var termList = terms.ToList(); 

    return amountTable.Where(t => termList.Contains(t.MinAmount)) 
     .Select(x => new AmountRange(term would go here, x.MinAmount, x.MaxAmount)) 
     .ToList(); 
} 

Ainsi, en un mot, je veux obtenir les résultats suivants:

  • passe un tableau int [] (termes) que les paramètres.
  • Sélectionnez toutes les lignes où chaque valeur de terme se situe entre les valeurs de table MinAmount et Max.
+0

Je pense que vous êtes en arrière. Changer la fonction pour retourner la liste . Puis changez .First() en .List(). – jdweng

+0

@jdweng - l'exemple bove est ce qui existe actuellement pour un seul paramètre - ce n'est pas un travail en cours pour la nouvelle version. –

+0

pourquoi renvoyez-vous 'First' et pas' ToList'? Si c'est l'algorithme que vous êtes sûr à 100% que cela fonctionne correctement, alors je n'ai aucun argument. Je demande juste pour que je puisse fournir la bonne réponse. –

Répondre

-1
public static AmountRange GetAmountRange(int[] terms) 
{ 
    return amountTable 
     .Where(x => terms.All(y => y.IsBetween(x.MinTerm, x.MaxTerm))) 
     .Select(x => new AmountRange(terms, x.MinAmount, x.MaxAmount)) 
     .ToList(); 
} 

Une autre approche

public static List<AmountRange> GetAmountRange(int[] terms) 
{ 
    return amountTable 
     .Select(x => new {Item=x, Terms=terms.Where(z => z.IsBetween(x.MinTerm, x.MaxTerm))}) 
     .SelectMany(x => x.Terms.Select(term => new AmountRange(term, x.Item.MinAmount, x.Item.MaxAmount))) 
     .ToList(); 
} 
+0

cela devrait retourner 'Liste ' pas 'AmountRange' –

+0

@ M.kazemAkhgary - Je pense que vous avez la mauvaise idée, le premier exemple était juste un exemple de la façon dont il est fait comme une seule rangée. –

+0

Si vous renvoyez un seul article pour une entrée unique, je suppose que vous devez retourner plusieurs articles pour plusieurs entrées. si ce n'est pas le cas ici, alors votre question n'est pas claire. Approfondissez vos explications, s'il vous plaît. Dans votre deuxième exemple, vous renvoyez également plusieurs éléments. @JohnOhara –

0

Ce que je voudrais faire est de faire une autre variante qui accepte un tableau de « int [] » comme la première de telle sorte que param je ne suis pas appel à la requête plusieurs fois.

Vous pouvez utiliser un dictionnaire de int à AmountRange. Autrement dit, chaque int distinct est mappé à un seul .

public static Dictionary<int, AmountRange> GetAmountRanges(int[] terms) 
{ 
    return terms.Distinct().ToDictionary(
       key => key, 
       term => amountTable 
       .Where(x => term.IsBetween(x.MinTerm, x.MaxTerm)) 
       .Select(x => new AmountRange(term, x.MinAmount, x.MaxAmount)) 
       .First()); 
} 

afin d'accéder aux éléments du dictionnaire.

var ranges = GetAmountRanges(terms); 

foreach(var kvp in ranges) 
{ 
    var index = kvp.Key; 
    var range = kvp.Value; 

    // do stuff 
} 

Si terms peut contenir des doublons, alors vous devriez accéder à des éléments de cette façon.

var ranges = GetAmountRanges(terms); 

foreach(var i in terms) 
{ 
    var kvp = ranges[i]; 
    var index = kvp.Key; 
    var range = kvp.Value; 

    // do stuff 
} 
1

tenu de l'objet:

public class AmountRange 
{ 
    public AmountRange(int term, int minAmount, int maxAmount) 
    { 
     Term = term; 
     MinTerm = minAmount; 
     MaxTerm = maxAmount; 
    } 

    public int Term { get; } 
    public int MinTerm { get; } 
    public int MaxTerm { get; } 
} 

Je pense que ce que vous cherchez est alors une jointure à des conditions passées et les termes du objet et ensuite appliquer le filtre en conséquence:

public static IEnumerable<AmountRange> GetAmountRange(int[] terms) 
    { 
     return amountTable 
      .Join(terms, 
       range => range.Term, 
       term => term, 
       (range, term) => new { range, term }) 
      .Where(x => x.term.IsBetween(x.range.MinTerm, x.range.MaxTerm)) 
      .Select(x => new AmountRange(x.term, x.range.MinTerm, x.range.MaxTerm)); 
    } 
+0

Merci pour votre effort - aller tester les réponses dès maintenant et vous récompenser dès que possible. –