2015-03-19 70 views
1

我需要返回一個值,該值與基於年齡的計算的某個權重相對應。處理數字範圍

這裏的年齡範圍和權重: -

21-30: 1.2 
31-40: 1.8 
41-50: 1.9 

等(有沒有真正的模式)

程序需要採取年齡作爲輸入,然後返回的權重(例如,如果年齡= 35,返回值是1.8。

這將如何做到最好?

我可以使用switch,但我不知道這是否是在最好的解決方法。是否還有一些其他的構造或技術可以在C#中應用,以實現這一點,如果權重發生變化,這將更加有效,便攜/可擴展?

另外一件事 - 我無法使用數據庫來存儲任何權重數據 - 只是將其添加到信息中。

回答

1

創建一個詞典來定義您的年齡範圍和權重。關鍵應與最小年齡和最大年齡此範圍內的元組和值應該是你的體重:

Dictionary<Tuple<int,int>, double> // minAge, MaxAge -> weight 

然後你可以遍歷所有鍵找到你的體重。

您可以從表格,XML文件,數據庫等內容創建該詞典。

+0

字典在這裏沒有真正的幫助,因爲你沒有'Tuple'來進行查找。也可能是一個List >。 – juharr 2015-03-19 12:00:19

+0

@juharr嗯,我只是使用它是一個鍵/值集合的事實,枚舉鍵的可能性。略微_simpler_使用比列表。 – DrKoch 2015-03-19 12:04:13

1

我們在這裏的系統中做了類似的工作,我們使用在數據庫表中存儲權重和閾值下限的概念。因此,我們需要做的就是找到具有最低下限閾值的記錄,小於輸入的值並讀取重量。

這簡化了過程,並允許編輯和添加和刪除值。

+0

忘了添加 - 我不能使用數據庫表來實現這一點。對不起 - 忘了提及。 – 2015-03-19 11:39:54

1

如果因爲他們似乎是在你的榜樣範圍是連續的,你只需要上限值,爲了能夠查詢其排序的範圍,所以你可以做這樣的事情:

public class RangeEntry 
{ 
    public RangeEntry(int upperValue, float weight) 
    { 
     UpperValue = uperValue; 
     Weight = weight; 
    } 

    public int UpperValue { get; set; } 
    public float Weight { get; set; } 
} 

public class RangeWeights 
{ 
    private List<RangeEntry> _ranges = new List<RangeEntry> 
    { 
     new RangeEntry(30, 1.2f), 
     new RangeEntry(40, 1.8f), 
     new RangeEntry(50, 1.9f), 
    } 

    public float GetWeight(int value) 
    { 
     // If you pre-sort the ranges then you won't need the below OrderBy 
     foreach (var r in _ranges.OrderBy(o => o.UpperValue)) 
     { 
      if (value <= r.UpperValue) 
       return r.Weight; 
     } 

     // Range not found, do whatever you want here 
     throw new InvalidOperationException("value not within in any valid range"); 
    } 
} 

這種方法的價值在於添加一個新的範圍意味着在範圍的實例化中僅添加1行代碼。

+0

在你的'RangeEntry'構造函數中''weight'參數應該是'float'而不是'int'。 – juharr 2015-03-19 12:15:30

+0

不錯的地方!修訂。 – 2015-03-19 13:01:42

0

不,據我所知,沒有什麼像範圍結構。

你可以以這種方式使用的開關,或者說,如果範圍總是從X1到Y0

switch((value-1)/10) 
{ 
    case 1: ... break; 
    case 2: ... break; 
} 

或者,如果需要的話:

switch(value) 
{ 
    case 11: 
    case 12: 
    case 20: ... break; 
    case 21: ... 
} 

根據羣體的數量,您需要,你可以做檢查,如

if(value > 10 && <= 20) ... 

我不知道有什麼更優雅的方法。

0

這不是很清楚什麼是年齡範圍和權重數據, 的結構,但我可能會做這樣的事情:

Class AgeRangeAndWeight { 
    int FromAge {get;set;} 
    int ToAge {get;set;} 
    double Weight {get;set;} 
} 

Class AgeRangeAndWeight Collection() : List<AgeRangeAndWeight> { 
    AgeRangeAndWeight FindByAge(int age) { 
    foreach(AgeRangeAndWeight araw in this) { 
     if(age >= araw.FromAge && age <= araw.ToAge) { 
     return araw; 
     } 
    } 
    return null; 
    } 
} 

那麼所有你需要做的就是調用FindByAge方法。記得檢查它是否不返回null。

1

如果範圍不重疊,那麼最好使用的是SortedList,其中鍵是範圍的上限值,該值是權重。此外,您可以通過權重來區分未找到條目的情況。我添加了{20, null}的條目,這樣如果年齡爲< = 20,您將獲得null而不是1.2。

var rangedWeights = new SortedList<int, float?> 
{ 
    { 20, null } 
    { 30, 1.2f }, 
    { 40, 1.8f }, 
    { 50, 1.9f } 
}; 

int age = 44; 
float? weight = null; 
foreach (var kvp in rangedWeights) 
{ 
    if (age <= kvp.Key) 
    { 
     weight = kvp.Value; 
     break; 
    } 
} 

您可以動態添加新條目,但仍然可以確保它們已排序。

rangedWeights.Add(60, 2.1f); 
1

您可以使用帶複合鍵的字典,您將使用它來檢查用戶輸入並獲取匹配鍵的推薦值。

這裏是例子;

 Dictionary<Tuple<int, int>, double> t = new Dictionary<Tuple<int, int>, double>(); 

     t.Add(new Tuple<int,int>(11,20),1f); 
     t.Add(new Tuple<int, int>(21, 30), 2f); 
     t.Add(new Tuple<int, int>(31, 40), 3f); 

     int weight = 34; 

     double rr = (from d in t where d.Key.Item1 <= weight && d.Key.Item2 >= weight select d.Value).FirstOrDefault(); 

     Console.WriteLine(rr); // rr will print 3.0  

希望它有助於..!

1

如果您正在尋找更短的寫作方式,我建議您使用?: operator

double getWeight(int age){ 
    return (age <= 30) ? 1.2 : 
      (age <= 40) ? 1.8 : 1.9; 
} 

它會和使用開關一樣。只有更短的方式把它。如果您不希望它們被硬編碼,您可以用變量替換數字和權重。