I need to compare 2 sets of string which have some similar names and I need to extract the similar names, how can I do that? They are both collections and lets say one of them is "Sanjay, Race" and the other is "Let, Sanjay", I need to extract Sanjay.
Depends on what data structure you have but I suggest you work with an Array or a List if you collection is big enough to care about optimisation.
You want to go through the first of the two lists, and for each element of list1, compare to compare to every element of list2. Be careful, this might take a while (if your collection is big enough).
Might look like :
using System.Collections.Generic;
LinkedList<string> set1 = new LinkedList<string>();
LinkedList<string> set2 = new LinkedList<string>();
LinkedList<string> extracted = new LinkedList<string>();
//fill in your sets with loops if needed :
see https://learn.microsoft.com/fr-fr/dotnet/api/system.collections.generic.linkedlist-1?view=net-7.0
foreach (string name in set1){
foreach (string name2 in set2){
if(string.Compare(name,name2)==0){
extracted.AddAfter(name);
}
}
}
Please, do correct me (nicely) :)
I have an array of List types:
List<object>[] vector = new List<object>[3];
The first List contains strings:
// Get word lists together, remove duplicates
var words = tableA.ToList().Union(tableB.ToList());
// Sort words
words = words.OrderBy(s => s, StringComparer.CurrentCultureIgnoreCase);
// Add words to the vector first slot
vector[0] = words.ToList<object>();
Now, I want to add ints to the second and third lists, but I get an error here:
vector[1].Add(tableA.GetValue(keyword));
vector[2].Add(tableB.GetValue(keyword));
GetValue() returns an int. But when I add these ints to the vector Lists it throws error:
ERROR Caught: Object reference not set to an instance of an object.
How should I add the ints to the List? Or is there some other data structure I should use instead for the vector? I feel there is some trivial cast I'm missing but I haven't been able find a solution.
I'm not an expert in C#, but i think i understand.
When you write :
List<object> vector = new List<object>[3];
you create a table of List with a size of 3.
You can put something into each slot of this array, but each "slot" still refers to no instance after this first line of code.
When you write
vector[0] = words.ToList<object>();
You put somehting into the first slot of vector list. But [1] and [2] are still empty. And
vector[1]
refers to a reference not set to an instance of an object. In short terms, it refers to nothing.
You must initialize each vector index value before add value. Thanks
When writing var a = new List<object> you´re only declaring that a is a list holding some (in your case three) items. However you don´t determine what stands in those three elements. You´d have to out some values into every single item, before you can anything with it (e.g. call any method).
You´re allready putting a list into the first item, however the elements on index one and two remain null causing a NullReferenceException when calling a method like the following:
vector[1].Add(...);
So you should initialize the value at index oe and two before:
vector[1] = new List<int>();
vector[2] = new List<int>();
But still you can´t do much with the list, because it is of type object, so you´d have to cast every element to the actual type:
((List<int>)vector[1]).Add(myInt);
Anyway I doubt storing three completely different lists within one single list alltogether is a good idea. Maybe you should define a class with the three lists as members instead:
class MyClass
{
public List<string> Words { get; set; }
public List<int> NumbersA { get; set; }
public List<int> NumbersB { get; set; }
}
A task that I can't seem to solve, even after hours and hours of trying.
Basically, I have a phonebook that takes input from the user: name and number (both string type), which becomes a Contact.
I'm supposed to store the Contact in an Array, and the user shall both be able to add and also delete data (Contact) from the array, via the methods Create and Delete.
I made an own Repository class to handle the data (Contact also has an own little class), but I used List to store the data, so I could simply use Add and Remove, so my code looks like this:
public class Repository
{
List<Contact> storagelist;
public Repository() {
storagelist = new List<Contact>();
}
public void Create(Contact item) //Adds the item to the list
{
storagelist.Add(item);
}
public bool Delete(Contact item) //Removes the item
{
if (!storagelist.Contains(item))
return false;
storagelist.Remove(item);
return true;
}
}
What I am looking for, is how do exactly this, have these 2 features of adding and removing a Contact, but store the data in an Array instead.
Since arrays (to my knowledge) has to have a fixed, pre-defined size I have no idea how it could be used in exactly the same way as the List. The array size shall always be the same as the amount of Contacts that are stored, but how can this be done when an array's size is fixed??
So, how to create an array, that always has the same size as the amount of Contacts that are stored, and how to Add and Remove to/from this array?
Help is very much appreciated!
EDIT: Thanks for all responses! Every answer was helpful in the process (Omar and person66 in particular!).
I solved the Removal by "moving" the entire array after the delete-element, to 1 index lower, and finally resizing the array to be smaller. Like so:
int deleteIndex = Array.IndexOf(storagelist, item);
for (int index = deleteIndex + 1; index < storagelist.Length; index++)
{
storagelist[index - 1] = storagelist[index];
}
Array.Resize(ref storagelist, storagelist.Length - 1);
You are right in that array sizes are fixed. You can, however, use Array.Resize() to create a new array of the specified size with all the current array data. So for adding you would resize to 1 larger and add the new contact at the end. For removing you will have to use a loop to shift all the elements in the array past the one being removed back one spot, then resize it to be 1 smaller.
EDIT: A simpler option for removing would be to use Array.Copy():
Array.Copy(a, deleteIndex + 1, a, deleteIndex, a.Length - (deleteIndex + 1));
Array.Resize(ref a, a.Length - 1);
A list is a much better solution to this problem, I don't know why you would ever want to use an array for this.
A List just ends up using an array for it's storage anyway. The way a list works is it is initializes an array with a certain amount of storage then if it's capacity is exceeded it recreates an array with a larger size and copies the elements back. You could try this approach, except you'd just be recreating what a list does.
The other option is just declare an arbitrarily large array of 100,000 elements or so. A number which you know will not be exceeded.
For size you can write your own function which keeps track of the number of contacts in the array.
You can use a generic list. Under the hood the List class uses an array for storage but does so in a fashion that allows it to grow effeciently.
Take a look at this link for more details, it can be helpfull.
var contacts = new[]
{
new { Name = "Foo", Phone = "9999999999" },
new { Name = "Bar", Phone = "0000000000" }
};
You can create an array of anonymous object and then use linq to delete objects from array.
You can create a new object and insert into anonymous object variable.
I'm making a program in C# that uses mathematical sets of numbers. I've defined the class Conjunto (which means "set" in spanish). Conjunto has an ArrayList that contains all the numbers of the set. It also has a string called "ID" which is pretty much what it sounds; the name of an instance of Conjunto.
The program have methods that applies the operations of union, intersection, etc, between the sets.
Everything was fine, but now i've a text file with sentences like:
A={1,2,3}
B={2,4,5}
A intersection B
B union A
And so on. The thing is, i don't know how many sets the text file contains, and i don't know how to name the variables after those sentences. For example, name an instance of Conjunto A, and name another instance B.
Sorry for the grammar, english is not my native language.
Thanks!
It's pretty complicated to create varaibles dynamically, and pretty useless unless you have some already existing code that expects certain variables.
Use a Dictionary<string, Conjunto> to hold your instances of the class. That way you can access them by name.
First off, If you don't target lower version than .Net 2.0 use List instead of ArrayList. If I were you I wouldn't reinvent the wheel. Use HashSet or SortedSet to store the numbers and then you can use defined union and intersection.
Secondly, what is your goal? Do want to have just the output set after all operations? Do you want to read and store all actions and them process it on some event?
First of all, your program is taken from bad side. I would advice to start making new one. One of ways to name "variables" dynamicaly is by making class objects and editing their properties.
This is what I made as a starting platform:
First af all I have crated a class called set
class set
{
public string ID { get; set; }
public List<int> numbers { get; set; }
}
Then I have made the code to sort whole textfile into list of those classes:
List<set> Sets = new List<set>();
string textfile = "your text file";
char[] spliter = new char[] { ',' }; //switch that , to whatever you want but this will split whole textfile into fragments of sets
List<string> files = textfile.Split(spliter).ToList<string>();
int i = 1;
foreach (string file in files)
{
set set = new set();
set.ID = i.ToString();
char[] secondspliter = new char[] { ',' }; //switch that , to whatever you want but this will split one set into lone numbers
List<string> data = textfile.Split(secondspliter).ToList<string>();
foreach (string number in data)
{
bool success = Int32.TryParse(number, out int outcome);
if (success)
{
set.numbers.Add(outcome);
}
}
i++;
Sets.Add(set);
}
Hope it helps someone.
.NET offers a generic list container whose performance is almost identical (see Performance of Arrays vs. Lists question). However they are quite different in initialization.
Arrays are very easy to initialize with a default value, and by definition they already have certain size:
string[] Ar = new string[10];
Which allows one to safely assign random items, say:
Ar[5]="hello";
with list things are more tricky. I can see two ways of doing the same initialization, neither of which is what you would call elegant:
List<string> L = new List<string>(10);
for (int i=0;i<10;i++) L.Add(null);
or
string[] Ar = new string[10];
List<string> L = new List<string>(Ar);
What would be a cleaner way?
EDIT: The answers so far refer to capacity, which is something else than pre-populating a list. For example, on a list just created with a capacity of 10, one cannot do L[2]="somevalue"
EDIT 2: People wonder why I want to use lists this way, as it is not the way they are intended to be used. I can see two reasons:
One could quite convincingly argue that lists are the "next generation" arrays, adding flexibility with almost no penalty. Therefore one should use them by default. I'm pointing out they might not be as easy to initialize.
What I'm currently writing is a base class offering default functionality as part of a bigger framework. In the default functionality I offer, the size of the List is known in advanced and therefore I could have used an array. However, I want to offer any base class the chance to dynamically extend it and therefore I opt for a list.
List<string> L = new List<string> ( new string[10] );
I can't say I need this very often - could you give more details as to why you want this? I'd probably put it as a static method in a helper class:
public static class Lists
{
public static List<T> RepeatedDefault<T>(int count)
{
return Repeated(default(T), count);
}
public static List<T> Repeated<T>(T value, int count)
{
List<T> ret = new List<T>(count);
ret.AddRange(Enumerable.Repeat(value, count));
return ret;
}
}
You could use Enumerable.Repeat(default(T), count).ToList() but that would be inefficient due to buffer resizing.
Note that if T is a reference type, it will store count copies of the reference passed for the value parameter - so they will all refer to the same object. That may or may not be what you want, depending on your use case.
EDIT: As noted in comments, you could make Repeated use a loop to populate the list if you wanted to. That would be slightly faster too. Personally I find the code using Repeat more descriptive, and suspect that in the real world the performance difference would be irrelevant, but your mileage may vary.
Use the constructor which takes an int ("capacity") as an argument:
List<string> = new List<string>(10);
EDIT: I should add that I agree with Frederik. You are using the List in a way that goes against the entire reasoning behind using it in the first place.
EDIT2:
EDIT 2: What I'm currently writing is a base class offering default functionality as part of a bigger framework. In the default functionality I offer, the size of the List is known in advanced and therefore I could have used an array. However, I want to offer any base class the chance to dynamically extend it and therefore I opt for a list.
Why would anyone need to know the size of a List with all null values? If there are no real values in the list, I would expect the length to be 0. Anyhow, the fact that this is cludgy demonstrates that it is going against the intended use of the class.
Create an array with the number of items you want first and then convert the array in to a List.
int[] fakeArray = new int[10];
List<int> list = fakeArray.ToList();
If you want to initialize the list with N elements of some fixed value:
public List<T> InitList<T>(int count, T initValue)
{
return Enumerable.Repeat(initValue, count).ToList();
}
Why are you using a List if you want to initialize it with a fixed value ?
I can understand that -for the sake of performance- you want to give it an initial capacity, but isn't one of the advantages of a list over a regular array that it can grow when needed ?
When you do this:
List<int> = new List<int>(100);
You create a list whose capacity is 100 integers. This means that your List won't need to 'grow' until you add the 101th item.
The underlying array of the list will be initialized with a length of 100.
This is an old question, but I have two solutions. One is fast and dirty reflection; the other is a solution that actually answers the question (set the size not the capacity) while still being performant, which none of the answers here do.
Reflection
This is quick and dirty, and should be pretty obvious what the code does. If you want to speed it up, cache the result of GetField, or create a DynamicMethod to do it:
public static void SetSize<T>(this List<T> l, int newSize) =>
l.GetType().GetField("_size", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(l, newSize);
Obviously a lot of people will be hesitant to put such code into production.
ICollection<T>
This solution is based around the fact that the constructor List(IEnumerable<T> collection) optimizes for ICollection<T> and immediately adjusts the size to the correct amount, without iterating it. It then calls the collections CopyTo to do the copy.
The code for the List<T> constructor is as follows:
public List(IEnumerable<T> collection) {
....
ICollection<T> c = collection as ICollection<T>;
if (collection is ICollection<T> c)
{
int count = c.Count;
if (count == 0)
{
_items = s_emptyArray;
}
else {
_items = new T[count];
c.CopyTo(_items, 0);
_size = count;
}
}
So we can completely optimally pre-initialize the List to the correct size, without any extra copying.
How so? By creating an ICollection<T> object that does nothing other than return a Count. Specifically, we will not implement anything in CopyTo which is the only other function called.
private struct SizeCollection<T> : ICollection<T>
{
public SizeCollection(int size) =>
Count = size;
public void Add(T i){}
public void Clear(){}
public bool Contains(T i)=>true;
public void CopyTo(T[]a, int i){}
public bool Remove(T i)=>true;
public int Count {get;}
public bool IsReadOnly=>true;
public IEnumerator<T> GetEnumerator()=>null;
IEnumerator IEnumerable.GetEnumerator()=>null;
}
public List<T> InitializedList<T>(int size) =>
new List<T>(new SizeCollection<T>(size));
We could in theory do the same thing for AddRange/InsertRange for an existing array, which also accounts for ICollection<T>, but the code there creates a new array for the supposed items, then copies them in. In such case, it would be faster to just empty-loop Add:
public void SetSize<T>(this List<T> l, int size)
{
if(size < l.Count)
l.RemoveRange(size, l.Count - size);
else
for(size -= l.Count; size > 0; size--)
l.Add(default(T));
}
Initializing the contents of a list like that isn't really what lists are for. Lists are designed to hold objects. If you want to map particular numbers to particular objects, consider using a key-value pair structure like a hash table or dictionary instead of a list.
You seem to be emphasizing the need for a positional association with your data, so wouldn't an associative array be more fitting?
Dictionary<int, string> foo = new Dictionary<int, string>();
foo[2] = "string";
The accepted answer (the one with the green check mark) has an issue.
The problem:
var result = Lists.Repeated(new MyType(), sizeOfList);
// each item in the list references the same MyType() object
// if you edit item 1 in the list, you are also editing item 2 in the list
I recommend changing the line above to perform a copy of the object. There are many different articles about that:
String.MemberwiseClone() method called through reflection doesn't work, why?
https://code.msdn.microsoft.com/windowsdesktop/CSDeepCloneObject-8a53311e
If you want to initialize every item in your list with the default constructor, rather than NULL, then add the following method:
public static List<T> RepeatedDefaultInstance<T>(int count)
{
List<T> ret = new List<T>(count);
for (var i = 0; i < count; i++)
{
ret.Add((T)Activator.CreateInstance(typeof(T)));
}
return ret;
}
You can use Linq to cleverly initialize your list with a default value. (Similar to David B's answer.)
var defaultStrings = (new int[10]).Select(x => "my value").ToList();
Go one step farther and initialize each string with distinct values "string 1", "string 2", "string 3", etc:
int x = 1;
var numberedStrings = (new int[10]).Select(x => "string " + x++).ToList();
string [] temp = new string[] {"1","2","3"};
List<string> temp2 = temp.ToList();
After thinking again, I had found the non-reflection answer to the OP question, but Charlieface beat me to it. So I believe that the correct and complete answer is https://stackoverflow.com/a/65766955/4572240
My old answer:
If I understand correctly, you want the List<T> version of new T[size], without the overhead of adding values to it.
If you are not afraid the implementation of List<T> will change dramatically in the future (and in this case I believe the probability is close to 0), you can use reflection:
public static List<T> NewOfSize<T>(int size) {
var list = new List<T>(size);
var sizeField = list.GetType().GetField("_size",BindingFlags.Instance|BindingFlags.NonPublic);
sizeField.SetValue(list, size);
return list;
}
Note that this takes into account the default functionality of the underlying array to prefill with the default value of the item type. All int arrays will have values of 0 and all reference type arrays will have values of null. Also note that for a list of reference types, only the space for the pointer to each item is created.
If you, for some reason, decide on not using reflection, I would have liked to offer an option of AddRange with a generator method, but underneath List<T> just calls Insert a zillion times, which doesn't serve.
I would also like to point out that the Array class has a static method called ResizeArray, if you want to go the other way around and start from Array.
To end, I really hate when I ask a question and everybody points out that it's the wrong question. Maybe it is, and thanks for the info, but I would still like an answer, because you have no idea why I am asking it. That being said, if you want to create a framework that has an optimal use of resources, List<T> is a pretty inefficient class for anything than holding and adding stuff to the end of a collection.
A notice about IList:
MSDN IList Remarks:
"IList implementations fall into three categories: read-only, fixed-size, and variable-size. (...). For the generic version of this interface, see
System.Collections.Generic.IList<T>."
IList<T> does NOT inherits from IList (but List<T> does implement both IList<T> and IList), but is always variable-size.
Since .NET 4.5, we have also IReadOnlyList<T> but AFAIK, there is no fixed-size generic List which would be what you are looking for.
This is a sample I used for my unit test. I created a list of class object. Then I used forloop to add 'X' number of objects that I am expecting from the service.
This way you can add/initialize a List for any given size.
public void TestMethod1()
{
var expected = new List<DotaViewer.Interface.DotaHero>();
for (int i = 0; i < 22; i++)//You add empty initialization here
{
var temp = new DotaViewer.Interface.DotaHero();
expected.Add(temp);
}
var nw = new DotaHeroCsvService();
var items = nw.GetHero();
CollectionAssert.AreEqual(expected,items);
}
Hope I was of help to you guys.
A bit late but first solution you proposed seems far cleaner to me : you dont allocate memory twice.
Even List constrcutor needs to loop through array in order to copy it; it doesn't even know by advance there is only null elements inside.
1.
- allocate N
- loop N
Cost: 1 * allocate(N) + N * loop_iteration
2.
- allocate N
- allocate N + loop ()
Cost : 2 * allocate(N) + N * loop_iteration
However List's allocation an loops might be faster since List is a built-in class, but C# is jit-compiled sooo...