Reputation: 39
In Visual Studio, using C#, I've got three arrays that look something like this:
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 };
The boolean cart represents checkboxes. Now what I want to do is, using a button, to check what boxes are ticked, and then sort of grab the name of the item from the array goods, and the price of it from the array price. Then I'll concatenate the strings, and add up the total sum, and just display that in a MessageBox.Show.
I'm thinking I need to tie the index of the cart array somehow to the corresponding indexes of the price and goods arrays. Or is there a better way of doing this? A for loop probably, but how? I'm not sure where to start. Help greatly appreciated!
Upvotes: 3
Views: 240
Reputation: 128
As suggested by others using a data model or a dictionary would be definitely better but if you want to stick to your original code of using arrays then you can use the following code :
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.
Upvotes: 0
Reputation: 14359
Though coding in C#, you are not object-oriented.
I agree with @JoelCoehoorn's comment about your current code demonstrating an anti-pattern. Below is my solution to that using Object Orientation.
Since price
and good
are referring to the same object, create an Item
class and add the members String Name;
and double Price;
to it.
As there is a Cart
, I'm sure the cart is in a store. So, create the Store
class as well.
Store
class, add a Dictionary<int, Item> AvailableItems;
that lists all the items available in the store (You can, instead of a Dictionary, use some other DS as well which makes sense in your case).Next, the customers who are coming to your store for purchasing anything should have a unique id assigned to them. This calls for a Customer
class. (Guest users can be assigned a new random id).
Dictionary<int, int> Cart;
which is a mapping of the id of the item they want to purchase and the count of the item.Lastly, we come to the Order
object that takes in a Cart
and has a nice method called PrintTotalSumFrom(Cart c)
which does exactly what you think it should.
A useful answer I wrote some time back about Object Oriented principles is here.
Upvotes: 0
Reputation: 131
One thing you can try is making a class Good
with properties Name
, Price
, Cart
, etc
public class Good
{
public string Name { get; set; }
public int Price { get; set; }
public bool Cart { get; set;}
}
and then putting them in a list.
List<Good> MyGoods = new List<Good>();
MyGoods.Add(new Good{ Name="item1", Price=100, Cart = false});
You can add as many Items as you want to that list and then iterate them with an index or with foreach
for(int i=0; i<MyGoods.Count;i++)
{
Console.WriteLine(MyGoods[i].Name);
}
or
foreach(Good g in MyGoods)
{
Console.WriteLine(g.Name);
}
Upvotes: 1
Reputation: 415600
is there a better way of doing this?
Matched array like this are an anti-pattern, and a sign you should really create a class with properties for price, good, and cart. Then you can have a single array that you can loop through just once.
But you can still do what you need, even with this anti-pattern:
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}");
This would also work, and might mean less memory use:
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}");
You can also use indexes:
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}");
And in this case the index option is probably faster and no more difficult to understand the the linq option (though it's very often the other way around), even though it's more code.
Upvotes: 3
Reputation: 834
This is a simple example of a binding problem.
I assume you have a checkbox for each of your items and when it's state changes the bool[] cart
changes at the correct index.
Then you just need to preserve that index and add up the right price and item like this:
string shoppingCart += goods[i];
decimal cost += price [i];
But, and that is a big one, you shouldn't rely on so many arrays based on the index.
As icebat mentioned in his comment you should implement a class representing your items.
Example:
public class Item
{
public int Id { get; set; }
public decimal Price { get; set; }
public string Name { get; set; }
}
Upvotes: 1
Reputation: 6965
You should definitely create an object that describes the items on sale.
however if you want to hack a horror together you can do something like this...
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
Upvotes: 0