LINQ

2010-04-26 17 views
12

के साथ भारित औसत की गणना करना मेरा लक्ष्य एक तालिका से भारित औसत प्राप्त करना है, दूसरी तालिका प्राथमिक कुंजी के आधार पर।LINQ

उदाहरण डेटा:

Table1

Key  WEIGHTED_AVERAGE 

0200 0 

तालिका 2

ForeignKey Length Value 
0200   105  52 
0200   105  60 
0200   105  54 
0200   105  -1 
0200   47  55 

मैं एक खंड की लंबाई के आधार पर एक भारित औसत प्राप्त करने की आवश्यकता है और मैं के मूल्यों की अनदेखी करने की जरूरत है -1 । मुझे पता है कि एसक्यूएल में ऐसा कैसे करें, लेकिन मेरा लक्ष्य LINQ में ऐसा करना है। यह एसक्यूएल में कुछ इस तरह दिखता है:

SELECT Sum(t2.Value*t2.Length)/Sum(t2.Length) AS WEIGHTED_AVERAGE 
FROM Table1 t1, Table2 t2 
WHERE t2.Value <> -1 
AND t2.ForeignKey = t1.Key; 

मैं अभी भी बहुत LINQ करने के लिए नया हूँ, और एक कठिन समय पता लगाना मैं यह कैसे अनुवाद होगा रही है। परिणाम भारित औसत लगभग 55.3 तक आना चाहिए। धन्यवाद।

उत्तर

33

मैं यह पर्याप्त है कि मैं एक बनाया करते हैं LINQ के लिए विस्तार विधि।

public static double WeightedAverage<T>(this IEnumerable<T> records, Func<T, double> value, Func<T, double> weight) 
{ 
    double weightedValueSum = records.Sum(x => value(x) * weight(x)); 
    double weightSum = records.Sum(x => weight(x)); 

    if (weightSum != 0) 
     return weightedValueSum/weightSum; 
    else 
     throw new DivideByZeroException("Your message here"); 
} 

के बाद आप डेटा के अपने सबसेट प्राप्त कॉल इस तरह दिखता है।

double weightedAverage = records.WeightedAverage(x => x.Value, x => x.Length); 

यह बेहद आसान हो गया है क्योंकि मुझे उसी रिकॉर्ड के भीतर किसी अन्य क्षेत्र के आधार पर डेटा के किसी भी समूह का भारित औसत प्राप्त हो सकता है।

अद्यतन

मैं अब शून्य से विभाजित करने के लिए जाँच करें और बजाय 0. लौटने के एक अधिक विस्तृत अपवाद फेंक उपयोगकर्ता अपवाद को पकड़ने और उन्हें आवश्यकतानुसार को संभालने के लिए अनुमति देता है।

+1

धन्यवाद, बहुत उपयोगी है। मैं इस एक एक लाइनर ... सार्वजनिक स्थिर नाव WeightedAverage बनाने को बंद कर (इस IEnumerable आइटम, समारोह मूल्य, समारोह वजन) { वापसी items.Sum (मद => मूल्य (आइटम) * वजन (आइटम))/आइटम.Sum (वजन); } – josefresno

+2

मुझे जोड़ना था "अगर भारित Sum.AlmostZero() वापसी 0" शून्य के द्वारा विभाजन के खिलाफ सुरक्षा के लिए गणना के बाद जब सभी वजन और सभी मान शून्य होते हैं। यदि कोई डबल शून्य है तो AlmostZero एक एक्सटेंशन फ़ंक्शन चेक है। – derdo

4

यदि आप निश्चित हैं कि तालिका 2 में प्रत्येक विदेशी कुंजी के लिए तालिका 1 में एक समान रिकॉर्ड है, तो आप केवल समूह बनाने में शामिल होने से बच सकते हैं। इस तरह आप एक विशिष्ट foreign_key के लिए wheighted_average प्राप्त कर सकते है

IEnumerable<int> wheighted_averages = 
    from record in Table2 
    where record.PCR != -1 
    group record by record.ForeignKey into bucket 
    select bucket.Sum(record => record.PCR * record.Length)/
     bucket.Sum(record => record.Length); 

अद्यतन

:

उस मामले में, LINQ क्वेरी इस तरह है।

IEnumerable<Record> records = 
    (from record in Table2 
    where record.ForeignKey == foreign_key 
    where record.PCR != -1 
    select record).ToList(); 
int wheighted_average = records.Sum(record => record.PCR * record.Length)/
    records.Sum(record => record.Length); 

ToList विधि जब रिकॉर्ड प्राप्त करने में कठिनाई कहा जाता है, क्वेरी दो बार निष्पादित करते समय दो अलग-अलग बीमा राशि के संचालन में रिकॉर्ड के योग से बचना है।

+0

यह प्रत्येक अलग विदेशीकी के लिए एक मूल्य देता है। यदि आप केवल एक विशिष्ट व्यक्ति और केवल विदेशी के लिए पहना हुआ औसत चाहते हैं, तो आप ग्रुपबी से बच सकते हैं, और रिकॉर्ड को वांछित विदेशी कुंजी के साथ फ़िल्टर कर सकते हैं, और बाद में एकत्रीकरण संचालन कर सकते हैं। मैं आपको दिखाने के लिए अपना जवाब संपादित करूंगा। – Fede

1

(ऊपर जवाब देने के लिए jsmith की टिप्पणी का उत्तर देना)

आप कुछ संग्रह के माध्यम से चक्र करने की इच्छा नहीं है, तो आप कोशिश कर सकते हैं निम्नलिखित:

var filteredList = Table2.Where(x => x.PCR != -1) 
.Join(Table1, x => x.ForeignKey, y => y.Key, (x, y) => new { x.PCR, x.Length }); 

int weightedAvg = filteredList.Sum(x => x.PCR * x.Length) 
    /filteredList.Sum(x => x.Length); 
+0

बस इतना ही पता है, मेरा समाधान मानता है कि आप पंक्तियों के एक सेट पर भारित औसत की गणना करना चाहते हैं, जिनकी विदेशी कुंजी पहली तालिका में किसी भी पंक्ति के मुख्य मूल्य से मेल खाती है। फेडे का समाधान आपको एक विशिष्ट विदेशी कुंजी के लिए पंक्तियां प्राप्त करेगा। तो, जो भी समाधान अधिक उचित है चुनने के लिए स्वतंत्र महसूस करें। –

संबंधित मुद्दे