如何根据其值获取字典数组中的项的键?

时间:2017-01-21 21:14:01

标签: c# asp.net

以下方法打印出来:

Minimum Temperature is 16
Maximum Temperature is 27
The Average Temperature is 22 

现在我想要除温度之外我还有温度最大和最小的日子,如:

Minimum Temperature is 16 on Day 6
Maximum Temperature is 27 on Day 8
The Average Temperature is 22

以下是将Day和Temperature作为字典参数插入数组并将其传递给确定最小值,最大值,平均值的方法的方法。

min和max是字典的int值,我的问题是我们如何根据这些值确定相关的字符串日?

 // if user select January , the January() execute:

 protected void Button1_Click(object sender, EventArgs e)
{
    // assigning Days and Temperatures to Dictionary and making array dictionary

    Dictionary<string, int>[] temperatures = new Dictionary<string, int>[10];
    temperatures[0] = new Dictionary<string, int>();
    temperatures[1] = new Dictionary<string, int>();
    temperatures[2] = new Dictionary<string, int>();
    temperatures[3] = new Dictionary<string, int>();
    temperatures[4] = new Dictionary<string, int>();
    temperatures[5] = new Dictionary<string, int>();
    temperatures[6] = new Dictionary<string, int>();
    temperatures[7] = new Dictionary<string, int>();
    temperatures[8] = new Dictionary<string, int>();
    temperatures[9] = new Dictionary<string, int>();

    temperatures[0].Add("Day1", 22);
    temperatures[1].Add("Day2", 23);
    temperatures[2].Add("Day3", 25);
    temperatures[3].Add("Day4", 26);
    temperatures[4].Add("Day5", 18);
    temperatures[5].Add("Day6", 16);
    temperatures[6].Add("Day7", 17);
    temperatures[7].Add("Day8", 27);
    temperatures[8].Add("Day9", 23);
    temperatures[9].Add("Day10", 24);
    if (DropDownList1.SelectedValue.ToString() == "January")
    {
        January(temperatures);
    }

  //the metthod which calculate min ,max and ..
 private void January(Dictionary<string, int>[] temperatures)
{
    int Minimumtemperture = 40;
    int Maximumtemperture = 0;
    int total = 0;
    int averageTemperatures = 0;
    // this foreach goes through array
    foreach (var temperture in temperatures)
    {

        // this foreach goes throuh dictionary 
        foreach (var degree in temperture)
        {                
            //assigning value of each dictionary to the monthTemp
            int MonthTemps = degree.Value;
            if (MonthTemps < Minimumtemperture)
            {
                Minimumtemperture = MonthTemps;
            }
            if (MonthTemps>Maximumtemperture)
            {
                Maximumtemperture = MonthTemps;
            }
            total = total + MonthTemps;

        }

        int totaltemperature = temperatures.Length;
        averageTemperatures = (total / totaltemperature);

    }

    // printing the result 

    Label1.Text = string.Format("Minimum Temperature is {0}<br/> Maximum Temperature is{1}<br/> The Average Temperature is{2}<br/>", Minimumtemperture, Maximumtemperture, averageTemperatures);

}

3 个答案:

答案 0 :(得分:3)

您遇到此问题,因为您的数据结构不适合该作业。 Dictionary<string, int>[]不会削减它。所以请耐心等待,并阅读这个长篇答案......

引入您自己的类以将属性组合在一起。班级Measurement包含数据。

// single data point
public class Measurement {
    public string Day { get; set; }
    public int Temperature { get; set; }
}

类也可以封装计算。外部只消耗结果,因此您可以更改基础实现。重要的是,这将使您的代码更容易理解。

班级Month隐藏计算。使用ICollection<Measurement>LINQ实现计算。

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

// groups measurements for a certain month and does calculations for this month
public class Month {

    public Month(string name) {
        Name = name;
        Measurements = new List<Measurement>();
    }

    // dictionary key
    public string Name { get; private set; }

    // note that the outside only knows we use an ICollection,
    // that we actually use a List in our implementation is hidden from them
    public ICollection<Measurement> Measurements { get; private set;}

    // to answer your original question:
    // LINQ .Min(m => m.Temperature) and .Max() would only return int
    // sorting will allow you to return the full Measurement, including the day
    // OrderBy runs in O(log(n)), see http://stackoverflow.com/q/3188693/1450855
    public Measurement MinByTemp { get { 
        return Measurements.OrderBy(m => m.Temperature).First(); 
    } }
    public Measurement MaxByTemp { get { 
        return Measurements.OrderBy(m => m.Temperature).Last(); 
    } }

   // more LINQ goodness
   // beware: all these getters cause recalculation each time they are called!
   // on the plus side, the results are always up to date
   public double Average { get { return Measurements.Average(r => r.Temperature); } }   
}

仔细查看LINQ,这将为您节省大量编写for循环的时间。可以通过实施IComparable来扩展Orderby()排序。

此控制台程序显示了如何使用这些类。它创建月份"January",按名称查找并执行计算。

public class Program {
    public static void Main() {

        // creating measurements
        var january = new Month("January");
        january.Measurements.Add(new Measurement { Day = "Day1", Temperature = 22 });
        january.Measurements.Add(new Measurement { Day = "Day2", Temperature = 25 });
        january.Measurements.Add(new Measurement { Day = "Day3", Temperature = 26 });
        january.Measurements.Add(new Measurement { Day = "Day4", Temperature = 18 });
        january.Measurements.Add(new Measurement { Day = "Day5", Temperature = 16 });
        january.Measurements.Add(new Measurement { Day = "Day6", Temperature = 17 });

        // finding months by their name
        // using a dictionary will perform this lookup in O(1)
        var months = new Dictionary<string, Month>();
        months.Add(january.Name, january);

        var selectedValue = "January"; // DropDownList1.SelectedValue.ToString();
        if (months.ContainsKey(selectedValue)) {
            var selectedMonth = months[selectedValue];

            // do calculations for the selected month
            // how the calculations are performed is encapsulated
            Measurement max = selectedMonth.MaxByTemp; // call getter only once
            string averageTemp = string.Format("{0:0.00}", selectedMonth.Average);

            // Label1.Text = string.Format(
            Console.WriteLine(selectedMonth.Name + ": Max " + max.Temperature + 
                " (on " + max.Day + ") Avg " +  averageTemp);
        }
        else {
            throw new KeyNotFoundException("Month not found: " + selectedValue);
        }
    }
}

完整示例:.Net Fiddle

答案 1 :(得分:1)

这是我尝试让它变得更容易。在文件的开头:

using KVP = System.Collections.Generic.KeyValuePair<string, int>; 

然后(或者只是将所有“KVP”替换为“KeyValuePair<string, int>”):

KVP[] temperatures = {
    new KVP("Day 1", 22),
    new KVP("Day 2", 23),
    new KVP("Day 2", 25),
    new KVP("Day 2", 26),
    new KVP("Day 2", 18),
    new KVP("Day 2", 16),
    new KVP("Day 2", 17),
    new KVP("Day 2", 27),
    new KVP("Day 2", 23),
    new KVP("Day 2", 24)
};

ILookup<int, string> lookup = temperatures.ToLookup(p => p.Value, p => p.Key);

//string example1 = string.Join(", ", lookup[23]);              // "Day 2, Day 2"
//string example2 = string.Join(", ", lookup[23].Distinct());   // "Day 2"

int min = lookup.Min(p => p.Key);                               // 16
int max = lookup.Max(p => p.Key);                               // 27

//var avg = lookup.Average(p => p.Key);                         // 22.0 (incorrect)
var avg = temperatures.Average(p => p.Value);                   // 22.1

var minDays = string.Join(", ", lookup[min].Distinct());        // "Day 2"
var maxDays = string.Join(", ", lookup[max].Distinct());        // "Day 2"

似乎Dictionary<string, int[]>(每天的温度数组)在您的情况下会更合适,但我使用了一组键值对来简化示例。

ILookup<int, string>类似于Dictionary<int, string[]>,其中每个键(温度)都有多个值(天)。

答案 2 :(得分:-1)

您可以使用LINQ执行此操作:

var dict = new Dictionary<string, int>();
dict.Add("a", 3);
dict.Add("b", 4);
dict.Add("c", 5);
dict.Add("d", 6);

int value = 5; // or whatever
string key = dict.Where(kvp => kvp.Value == value)
                    .Select(kvp => kvp.Key)
                    .FirstOrDefault();

请注意,如果您有多个包含相同值的键,则可能会遇到一些碰撞问题。在这种情况下,您只需将FirstOrDefault()替换为ToArray()即可获得一系列符合给定值的键。