Is there an easy way, and most importantly, more optimized to do the fowling code:
class Chair{
int numberOfLegs=4;
}
class House{
Chair chair;
String name="My Home";
}
// add chairs to each house
IList<Chair> chairs = new List<Chair>(10); // let us imagine that we have 10 different chairs...
// Code to replace:
IList<House> houses = new List<House>(chairs.Count());
for (int i = 0; i < houses.Count(); i++){
houses[i].chair = chairs[i]
}
My own suggestion it is replacing the for with Linq
// Code to replace:
IList<Homes> homes = chairs.Select(c => new Home{ Chair = c}).ToList();
Is it faster than the old code?
Do you have a better idea? Maybe using chairs.AsParallel?
Related
using System;
using System.Collections.Generic;
using ConsoleApp3;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
Customers customers = new Customers();
List<Customers> names = new List<Customers>()
{
new Customers {Names = "Tanveer"},
new Customers {Names = "Nabila"},
new Customers {Names = "Suraj"}
};
foreach (int i = 0; i < names.Count; i++)
{
Console.WriteLine(customers.Names.Length);
}
}
class Customers
{
public string Names { get; set; }
}
}
}
I want to create the list of Customers and write it on the Console. But the Customers.Names is null. I am new to programming so please help.Thanks
First, let us fix up that naming. Naming is very important, but also one of the more annoying parts.
//Singular for the class
class Customer
{
//Also Singular, as this can only take 1 name
public string Name { get; set; }
}
//Plural, because it is a collection of Customer Instances.
List<Customer> Customers = new List<Customer>()
{
new Customer {Name = "Tanveer"},
new Customer {Name = "Nabila"},
new Customer {Name = "Suraj"}
};
Then you itterate over it using:
//Use a proper foreach, no need to deal with Indexes here
foreach (Customer current in Customers){
Console.WriteLine(current.Name);
}
If you do want to have a running counter, this is how the loop would look:
for(int i = 0; i < Customers.Count;i++){
//I you get any Exceptions, you want to split it up over 2 lines using a temporary variable
Console.WriteLine(Customers[i].Name);
}
What you had in your code was a bastardisation of for and foreach syntax, wich I doubt compiled.
Console.WriteLine(names[i].Names);
customers.Names is null because customers is an object which you haven't populated with any data, and has no obvious purpose. names is the actual list of customers with useful info in it.
names does not have a Names property directly either, though. The objects within the list do. So you need to refer to a specific object within the specific list.
And since you're in a loop for doing just that, names[i].Names.Length is no doubt what you intended.
N.B. However it needs to be a for rather than foreach in the loop definition - the syntax used with foreach is different. This shouldn't have compiled in order to allow you to even see the null output, so perhaps this is just a typo in your posted code.
for (int i = 0; i < names.Count; i++)
{
Console.WriteLine(names[i].Names.Length);
}
should be closer to what you need (although I'm not convinced you really are intending to print the length of each name...but that's up to you).
P.S. You should probably amend your naming convention so you've got Customer as the type and Name as the property. It's much more readable and comprehensible if they're singular rather than plural.
I have a list that is constantly being updated throughout my program. I would like to be able to compare the initial count and final count of my list after every update. The following is just a sample code (the original code is too lengthy) but it sufficiently captures the problem.
class Bot
{
public int ID { get; set; }
}
public class Program
{
public void Main()
{
List<Bot> InitialList = new List<Bot>();
List<Bot> FinalList = new List<Bot>();
for (int i = 0; i < 12345; i++)
{
Bot b = new Bot() {ID = i};
InitialList.Add(b);
}
FinalList = InitialList;
for (int i = 0; i < 12345; i++)
{
Bot b = new Bot() {ID = i};
FinalList.Add(b);
}
Console.Write($"Initial list has {InitialList.Count} bots");
Console.Write($"Final list has {FinalList.Count} bots");
}
}
Output:
Initial list has 24690 bots
Final list has 24690 bots
Expected for both lists to have 12345 bots.
What is correct way to copy the initial list so new set is not simply added to original?
To do what you seem to want to do, you want to copy the list rather than assign a new reference to the same list. So instead of
FinalList = InitialList;
Use
FinalList.AddRange(InitialList);
Basically what you had was two variables both referring to the same list. This way you have two different lists, one with the initial values and one with new values.
That said, you could also just store the count if that's all you want to do.
int initialCount = InitialList.Count;
FinalList = InitialList;
Although there's now no longer a reason to copy from one to the other if you already have the data you need.
I get the feeling you actually want to do more than what's stated in the question though, so the correct approach may change depending on what you actually want to do.
I'm trying to put together a list (let's call this FinalList) using the combined values of two lists: Customers and Products. Suppose we have four Customers and one Product, FinalList should have a final result of four items (one for each customer).
For example:
Customer List:
Customer Code | Customer Name | Customer Branch ID
------------------|-----------------------|------------------------
001 | Tom | T001
002 | Dick | T002
003 | Harry | T003
004 | Jerry | T004
Product List:
Product Code | Product Name
------------------|---------------------
P001 | Apple
Currently I'm trying to do it this way:
var finalList = new List<ProductDetailDto>();
var customerList = new List<CustomerGroup>();
/// productsList is also type List<ProductDetailDto>();
for (var j = 0; j<= productsList.Count()-1; j++)
{
for (int i = 0; i <= customerList.Count() - 1; i++)
{
var singleDetail = new ProductDetailDto();
// Copy current products to groupDetail
singleDetail = productsList[j];
// Assemble rest of the info
singleDetail.CustCode = customerList[i].Customer.CustomerCode;
singleDetail.CustName = customerList[i].Customer.CustomerName;
singleDetail.CustBranchId = customerList[i].Customer.CustomerBranchId;
finalList.Add(singleDetail);
}
}
return finalList;
After executing this however, finalList only used Jerry as customer for all four items. I tried using foreach as well with the same results. I'm not really sure what I did wrong here, and I'm embarrassed that this seems basic to some, so I'm hoping for a fresh set of eyes to spot what mistake I made here...
Also, is there any way I can further optimize this?
Any help will be greatly appreciated, as always. Thank you.
Here:
// Copy current products to groupDetail
singleDetail = productsList[j];
You don't actually copy current product, but you copy a reference to your item from productsList, and on every inner loop iteration you override properties in the same productsList[j] element.
You may want to read more on how assignment works on reference types:
https://www.microsoftpressstore.com/articles/article.aspx?p=2454676
You need to create a new object if you want to make a cross product of two lists:
var finalList = new List<ProductDetailDto>();
var customerList = new List<CustomerGroup>();
/// productsList is also type List<ProductDetailDto>();
for (var j = 0; j<= productsList.Count()-1; j++)
{
for (int i = 0; i <= customerList.Count() - 1; i++)
{
var singleDetail = new ProductDetailDto
{
ProductCode = productsList[j].ProductCode,
ProductName = productsList[j].ProductName
// and whatever other properties your product have
};
// Assemble rest of the info (these can actually go to object initializer too)
singleDetail.CustCode = customerList[i].Customer.CustomerCode;
singleDetail.CustName = customerList[i].Customer.CustomerName;
singleDetail.CustBranchId = customerList[i].Customer.CustomerBranchId;
finalList.Add(singleDetail);
}
}
return finalList;
As for me, it is confusing that you have properties like CustCode, CustName and CustBranchId in your ProductDetailDto. Are these properties just empty for objects in productsList? Consider creating another class specially for these needs like CustomerProductDto, so that your intention becomes more clear.
You can optimize this using LINQ:
var items = from p in productsList
from c in customerList
select new ProductDetailDto
{
ProductCode = p.ProductCode,
ProductName = p.ProductName
CustCode = c.Customer.CustomerCode,
CustName = c.Customer.CustomerName,
CustBranchId = c.Customer.CustomerBranchId,
};
return items.ToArray();
This line of code:
singleDetail = productsList[j];
affects a pointer and not values, so in the end you have a list of the same pointer so you have only the last modification repeated customerList.Count()
So you must add the values one by one like customerList
I am trying to create an array of 20 candidates from my Candidate class. So far, this is what I have:
Candidate candidate0 = new Candidate();
Candidate candidate1 = new Candidate();
Candidate candidate2 = new Candidate();
Candidate candidate3 = new Candidate();
...
Candidate candidate19 = new Candidate();
Candidate[] candidates = new Candidate[20];
candidates[0] = candidate0;
candidates[1] = candidate1;
candidates[2] = candidate2;
candidates[3] = candidate3;
...
candidates[19] = candidate19;
I know this is not the correct or 'best' way to do this. What would be the best way?
What you need is a for loop :
int candidateLength = 20 ;
Candidate[] candidates = new Candidate[candidateLength ];
for(int i=0 ; i<candidates.Length ; i++)
{
candidates[i] = new Candidate();
}
Adam - you'd be subjectively better off using a list for this along the lines of:
List<Candidate> canditateList = new List<Candidate>();
// MaxLength is a const defined somewhere earlier perhaps
for(int i=0 ;i<MaxLength;i++){
canditateList.Add(new Candidate(){... properties here});
}
// etc, etc.
You could then factor this out to an array if required using:
var candidateArray = canditateList.ToArray();
Just my initial thoughts, tho you may of course have a good reason for wishing to use an array from the start, my premise is that I would go with a list and party on that for various extracted flavours.
I'm creating a game where I'd like to generate a name for 16 different planets from a bank of names and assign them to a planet. I've created an array for the planets and the name generation logic which are featured below.
Planet[] planetArray = new Planet[16];
public static void NameGeneration()
{
List<String> planetNames = new List<String>()
{
"Bak'hur", "Etonia", "Laurellan",
"Ragki", "Metiope", "Defel",
"Liehne", "Rykhan", "Heito",
"Makha", "Cerbi", "Helios",
"Luruguan", "Chawnos", "T'hig",
"Blana", "Pergate V", "Shemon III",
"Yokteth", "Letry", "Last Besgino",
"Ayus", "Alterus", "Qurenos"
};
List<Tuple<int>> instances = new List<Tuple<int>>();
List<string> generatedNames = new List<string>();
Random random = new Random();
int planetName;
//generating 16 names
while(instances.Count < 16)
{
planetName = random.Next(0, planetNames.Count);
Tuple<int> tuple = new Tuple<int>(planetName);
if (instances.Contains(tuple))
{
instances.Add(tuple);
}
}
foreach (var tuple in instances)
{
generatedNames.Add(string.Format("{0}", planetNames[tuple.Item1]));
}
foreach (var n in generatedNames)
{
}
}
I really don't know where to go from here, though I have considered selecting from the list and assigning it manually, or randomising the planet aswell but I'd still be stuck in my tracks.
Any help or tips would be appreciated. Thank you.
Ryan
I believe this code does same thing - creates list of randomly picked 16 planet names:
var generatedNames = planetNames.OrderBy(n => random.Next()).Take(16).ToList();
You can use Linq to create the planets, after the random. Something like:
planetArray = generatedNames.Select(x=>new Planet(x)).ToArray();
BTW, Why do you use List of Tuple of int?. You can use List directly.