【问题标题】:Looping through arrays, tying values to each other循环遍历数组,将值相互绑定
【发布时间】:2019-04-19 19:01:39
【问题描述】:

在 Visual Studio 中,使用 C#,我得到了三个看起来像这样的数组:

int[] price = new int[] { 100, 200, 300, 400, 500, 600 };

string[] goods = new string[] { "item1", "item2", "item3", "item4", "item5", "item6" }; 

bool[] cart = new bool[] { false, false, false, false, false, false };

布尔购物车表示复选框。现在我要做的是,使用一个按钮,检查哪些框被打勾,然后从数组中获取商品的名称,并从数组价格中获取它的价格。然后我将连接字符串,并将总和相加,然后将其显示在 MessageBox.Show 中。

我想我需要以某种方式将购物车数组的索引与价格和商品数组的相应索引联系起来。或者有没有更好的方法来做到这一点?一个 for 循环可能,但如何?我不知道从哪里开始。 非常感谢您的帮助!

【问题讨论】:

  • 更好的方法是创建一个单独的类型(类),具有 Price、Name 和 IsChecked 等属性。他们您将只有一个集合,并且可以将所有具有 IsChecked == true 的对象的价格相加
  • 你可以制作一个包含Dictionary<string, int>("item1", 100)的映射字典
  • 有更好的方法。创建类来存储您的数据模型,然后使用集合来存储您的数据模型列表。这称为 OOP
  • 所有这些数据从何而来? 有没有更好的方法来做到这一点几乎可以肯定是的,但如果没有更多信息,目前还不清楚这种方法会是什么
  • 您能否更具体地了解“连接字符串”?你期待什么样的字符串结果?

标签: c# arrays loops


【解决方案1】:

有更好的方法吗?

像这样的匹配数组是一种反模式,并且表明您应该真正创建一个具有价格、商品和购物车属性的类。然后你可以有一个数组,你可以循环一次。

但即使使用这种反模式,您仍然可以做您需要的事情:

var items = cart.Zip(goods, (c,g) => new {Cart = c, Good = g}).Zip(price, (a, p) => new {Cart = a.Cart, Good = a.Good, Price = p});
var ticked = items.Where(i => i.Cart);

var message = string.Join(",", ticked.Select(t => t.Good));
var sum = ticked.Select(t => t.Price).Sum();

MessageBox.Show($"{message}\nTotal: {sum}");

这也可以,并且可能意味着更少的内存使用:

var ticked = cart.Select((value,index) => new {Cart = value, Price = price[index], Good = goods[index]})
    .Where(i => i.Cart);
var message = string.Join(",", ticked.Select(s => s.Good));
var sum = ticked.Select(s => s.Price).Sum();

MessageBox.Show($"{message}\nTotal: {sum}"); 

你也可以使用索引:

int sum = 0;
var message = new StringBuilder();
var delimiter = "";
for(int i = 0; i<cart.Length; i++)
{
    if (cart[i])
    {
       sum += price[i];
       message.Append(delimiter).Append(goods[i]);
       delimiter = ",";
    }
}
MessageBox.Show($"{message}\nTotal: {sum}");

在这种情况下,index 选项可能更快,并且更容易理解 linq 选项(尽管它通常是相反的),即使它的代码更多。

【讨论】:

    【解决方案2】:

    您绝对应该创建一个描述特价商品的对象。

    但是,如果你想一起破解恐怖,你可以做这样的事情......

    int[] price = new int[] { 100, 200, 300, 400, 500, 600 };
    
    string[] goods = new string[] { "item1", "item2", "item3", "item4", "item5", "item6" }; 
    
    bool[] cart = new bool[] { false, false, true, false, false, true };
    
    var selected = cart.Select((value,index) => new {value, index})
        .Where(item => item.value == true)
        .Select(item => item.index)
        .ToList();
    
    int total = 0;
    
    foreach(var x in selected){
        total += price[x];
    }
    
    //total is 900
    

    【讨论】:

      【解决方案3】:

      这是一个绑定问题的简单示例。

      我假设您的每个项目都有一个复选框,当它的状态发生变化时,bool[] cart 会在正确的索引处发生变化。

      然后您只需要保留该索引并将正确的价格和项目相加,如下所示:

      string shoppingCart += goods[i];
      
      decimal cost += price [i];
      

      但是,这是一个很大的问题,您不应该依赖这么多基于索引的数组。

      正如 icebat 在他的评论中提到的,你应该实现一个代表你的项目的类。

      例子:

      public class Item
      {
          public int Id { get; set; }
          public decimal Price { get; set; }
          public string Name { get; set; }
      }
      

      【讨论】:

        【解决方案4】:

        正如其他人所建议的那样,使用数据模型或字典肯定会更好,但如果您想坚持使用数组的原始代码,那么您可以使用以下代码:

        int[] price = new int[] { 100, 200, 300, 400, 500, 600 };
        
        string[] goods = new string[] { "item1", "item2", "item3", "item4", "item5", "item6" };
        
        bool[] cart = new bool[] { false, false, false, false, false, false };
        
        StringBuilder sb = new StringBuilder();
        int totalPrice = 0;
        for(int i = 0; i < cart.Length; i++)
        {
            if (!cart[i]) continue;
            sb.Append(goods[i]);
            totalPrice += price[i];
        }
        //Use sb.ToString() and totalPrice to show in Messagebox.
        

        【讨论】:

          【解决方案5】:

          您可以尝试的一件事是使用属性NamePriceCart 等创建一个类Good

          public class Good
          {
              public string Name { get; set; }
              public int Price { get; set; }
              public bool Cart { get; set;}
          
           }
          

          然后将它们放在一个列表中。

          List<Good> MyGoods = new List<Good>();
          MyGoods.Add(new Good{ Name="item1", Price=100, Cart = false});
          

          您可以向该列表添加任意数量的项目,然后使用索引或 foreach 对其进行迭代

          for(int i=0; i<MyGoods.Count;i++)
          {
              Console.WriteLine(MyGoods[i].Name);
          }
          

          foreach(Good g in MyGoods)
          {
              Console.WriteLine(g.Name);
          }
          

          【讨论】:

            【解决方案6】:

            虽然用 C# 编码,但你不是面向对象的。

            我同意@JoelCoehoorn 关于您当前代码演示反模式的评论。下面是我使用面向对象的解决方案。


            • 由于pricegood 指的是同一个对象,创建一个Item 类并将成员String Name;double Price; 添加到它。

            • 由于有Cart,我确定购物车在商店中。所以,也要创建Store 类。

              • Store 类中,添加一个 Dictionary&lt;int, Item&gt; AvailableItems; 以列出商店中的所有可用商品(您也可以使用其他一些对您的情况有意义的 DS,而不是 Dictionary)。
            • 接下来,来您的商店购买任何东西的客户应该有一个唯一的 ID。这需要一个Customer 类。 (可以为访客用户分配一个新的随机 id)。

              • 客户还会有一个Dictionary&lt;int, int&gt; Cart;,这是他们要购买的商品的 ID 和商品数量的映射。
            • 1234563

            我不久前写的一个关于面向对象原则的有用答案是here

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2013-03-25
              • 2015-04-16
              • 2019-12-11
              • 2014-06-04
              • 1970-01-01
              相关资源
              最近更新 更多