Change arraylist to generic - c#

I am using below code :
var list = new Collection<ArrayList>
{
new ArrayList
{
1,
"Test1"
},
new ArrayList
{
2,
"Test2"
},
};
In the above code I want to avoid the ArrayList and use the Generics. Is it possible in the above code?
Edit:
Above I have used only two values in one arraylist object, I may have multiple items of int's and string's in it.

You can't mix types in a generic list (unless the generic type is object, but that equates to ArrayList and is just a perversion of generics).
But you can create a class that contains a string and int and use that as the generic parameter for a generic list.
public class MyClass
{
public MyString string { get; set; }
public MyInt int { get; set; }
}
var list = new Collection<MyClass>
{
new MyClass { MyInt = 1, MyString = "Test1" },
new MyClass { MyInt = 2, MyString = "Test2" }
}
Another alternative, if using .NET 4.0 is to use a Tuple, though I would rather have a strongly typed class.
(untested code):
var list = new Collection<Tuple<int,string>>
{
Tuple.Create(1, "Test1"),
Tuple.Create(2, "Test2")
}

No.
The whole point of generics is that you can't put an int and a string in the same collection.
Instead, you should create your own class with int and string properties, then create a generic collection of that class.

Not really, the fact that you have different types makes using a generic pointless.
You could use List<object> instead of ArrayList but there's really no point. Instead you could create a custom class to hold the 2 values and use that in a generic type.
John

Maybe you need Dictionary?
var list = new Dictionary<int, string>
{
{ 1, "Test1" },
{ 2, "Test2" }
};

var list = new List < Dictionary<int, string>> ();
then you can populate it was data as you need.

I'm not sure what you are actually trying to achieve, but it seems to me you are trying to mimic the behavior of a dictionary or map, that can map two different values to each other. These values could be of any type you want.
Something like this:
Dictionary<int, string> d = new Dictionary<int, string>();
d.Add(1, "Test1");
d.Add(2, "Test2");
and you can handle your data as simple as:
string t1 = d[1]; //will hold "Test1"
string t2 = d[2]; //will hold "Test2"
Do you want something like this?

Related

how to use string.join to join all values from an object array?

I have the same situation as this user how to use string.join to join value from an object array? in this question. However, I want to join all values from the object instead of only 1 value.
To recap my question:
I have an array of object e.g:
MyObject[] objs;
and within MyObject it contains 3 string property,
object[0].stringValue1
object[0].stringValue2
object[0].stringValue3
If I want to join the whole array of objects by all of their stringValues (stringValues1,2 and 3), how can I do it?
I think selector doesn’t allow me to select several elements, then how to use string.join to join several values from an object array?
See below for example usage of the two extension methods provided in the implementation section below. The first allows you to select the properties to include, and the second includes all string properties of the object in the source collection which I believe is the exact answer to your question.
Example Usage
Note, the resulting output from the two examples below are ordered differently as a result of how each implementation works, however the results are otherwise identical as a result of the first example specifying all string properties on the MyObj sample type
Live Fiddle Example
// Test Object
public class MyObj
{
public MyObj(string prop1, string prop2, string prop3)
{
Prop1 = prop1;
Prop2 = prop2;
Prop3 = prop3;
}
public string Prop1 { get; set; }
public string Prop2 { get; set; }
public string Prop3 { get; set; }
}
// Sample Data
var list = new List<MyObj> {
new MyObj("A1", "B1", "C1"),
new MyObj("A1", "B2", "C2"),
new MyObj("A3", "B3", "C3")
};
Samples using above object and data
// Example #1 - All properties separated by single separator
Console.WriteLine(list.Join(colSeparator: ','));
// RESULT: A1,A1,A3,B1,B2,B3,C1,C2,C3
// Example #2 - Object property separator, and different object separator
Console.WriteLine(list.Join(colSeparator: ',', rowSeparator: '\n'));
// RESULT: A1,B1,C1
A1,B2,C2
A3,B3,C3
Implementation
public static class EnumerableStringJoinExtension
{
public static string Join<T>(this IEnumerable<T> values, char colSeparator, char? rowSeparator = null)
{
var strProperties = typeof(T).GetProperties().Where(r=>r.PropertyType == typeof(string));
var sb = new StringBuilder();
foreach(var val in values)
sb.Append(string.Join(colSeparator, strProperties.Select(r=> r.GetValue(val)))).Append(rowSeparator ?? colSeparator);
sb.Remove(sb.Length - 1, 1);
return sb.ToString();
}
}
A possible way to solve it is to first create an array of each object's properties (using .Select()), and then flatten the resulting property arrays by using .SelectMany(). Both of those methods are found in the System.Linq namespace. The resulting IEnumerable<string> object's items can then be joined using string.Join().
If MyObject is defined as
class MyObject
{
public string First { get; set; }
public string Second { get; set; }
public string Third { get; set; }
}
and you define objects as
List<MyObject> objects = new()
{
new() { First = "ABC", Second = "DEF", Third = "GHI" },
new() { First = "JKL", Second = "MNO", Third = "PQR" },
new() { First = "STU", Second = "VWX", Third = "YZ" },
};
, a possible implementation is:
var flattenedObjects = objects
.Select(obj => new[] { obj.First, obj.Second, obj.Third })
.SelectMany(properties => properties);
var objectString = string.Join("_", flattenedObjects);
Printing the value of objectString to the console gives:
ABC_DEF_GHI_JKL_MNO_PQR_STU_VWX_YZ
Example fiddle here.
If you just want a one-line, handy C# without hard-coding property name you could try this:
string.Join("\n", objs.Select(o => string.Join("_", o.GetType().GetProperties().Select(p => p.GetValue(o)))));
This produces the following result:
"A_B_C\nD_E_F\nG_H_I"
with the object array as:
var objs = new MyObject[]
{
new MyObject("A", "B", "C"),
new MyObject("D", "E", "F"),
new MyObject("G", "H", "I")
};
But please note that if your class has properties in other types then you might need a Where() between GetProperties() and the second Select() to exclude unwanted properties.

how to get corresponding "Name"

I have a C# dictionary in which I have a corresponding NAME against the ID.
Dictionary<string, List<object>> dict = new Dictionary<string, List<object>>
{
{ "ID", new List<object> { "Id1", "Id2" } },
{ "NAME", new List<object> { "True", "False" } }
};
foreach (var id in dict["ID"])
{
Console.WriteLine(id);
//how to get corresponding "Name". For "Id1" = "True" and for "Id2" = "False"
}
In above code I loop through ID, but how to get corresponding NAME?
I think a better design would be to create a class with the two properties and then iterate. If you find yourself having to sync different data structures for simple data representations then I'd suggest rethinking the design.
public class MyClass
{
public string Id { get; set; }
public bool Name { get; set; }
}
And then hold a List<MyClass> which when you iterate:
foreach (var item in list)
{
// Now access item.Id, item.Name
}
The use of dictionaries is good when you have some sort of natural key for your data and you want to access access an item by that key. As the items are accessed via a hash function accessing by key is done in O(1) whereas searching in a list is O(n). However in your case you are iterating all items in any case so no need for dictionary and arranging the data in a class is a better design.
A bit about the differences and some references:
what is the difference between list<> and dictionary<> in c#
List vs ArrayList vs Dictionary vs Hashtable vs Stack vs Queue?
If you do have control over dictionary data it's best to either use Gilad's answer and store everything in List<MyClass> or to use Dictionary<string, bool> :
Dictionary<string, bool> dict = new Dictionary<string, bool>()
{
{ "Id1", true }, { "Id2", false },
};
But if you do not have control over format of this data and get it as a dictionary from somewhere (for example web service) you could utilize .Zip method to convert this dictionary into one list of either anonymous objects/custom class or Tuples, where Item1 is Id and Item2 is value:
// anonymous object
var data = dict["ID"].Zip(dict["NAME"], (x, y) => new
{
ID = x,
NAME = y
}).ToList();
// tuple
// List<Tuple<object, object>> data = dict["ID"].Zip(dict["NAME"], Tuple.Create).ToList();
foreach (var obj in data)
{
Console.WriteLine(obj.ID + " " obj.NAME);
}
The other answers are probably what you should do to better structure your code. However, if you need to stick to your original use case, you could do something like this:
//Depending on what you're dealing with: Dictionary<string, List<string>>
Dictionary<string, List<object>> dict = new Dictionary<string, List<object>>{
{"ID", new List<object>{"Id1", "Id2"}},
{"NAME", new List<object>{"True", "False"}}
};
foreach(var v in dict.Keys){
Console.WriteLine($"{v} = {string.Join(",", dict[v])}");
}
//Output:
//ID = Id1,Id2
//NAME = True,False
Even if you have the just the mapping of ID and Name you can have very simple variable
Dictionary<string,string> lookup = new Dictionary<string,string>();
lookup.Add("ID1","True")
and if Name is Boolean type then replace string to bool in the
Dictionary<string,bool> lookup = new Dictionary<string,bool>();

How to add Terms into Terms Query (ElasticSearch NEST C#)?

I'm writing a TermsQuery in NEST. I have created a QueryContainer for it. Here is my code:
QueryContainer qc1 = new TermsQuery()
{
Field = "recordID",
Terms =
};
I want to add int array as Terms and it shows that terms only accept IEnumerable<object>. I have tried converting array to Enumbrable and it's not working.
I just want to know what kind of object Terms accept?
Thanks in advance.
Terms accepts an IEnumerable<object> so it can accept a collection of any objects :) The type to use will depend on the field that you are querying against.
Given the model
public class Document
{
public int Property1 { get; set; }
}
To pass it a collection of int or any other type
var termQuery = new TermsQuery
{
Field = Infer.Field<Document>(d => d.Property1),
Terms = new object[] { 1, 3, 5 }
};

Shortcut for creating single item list in C#

In C#, is there an inline shortcut to instantiate a List<T> with only one item.
I'm currently doing:
new List<string>( new string[] { "title" } ))
Having this code everywhere reduces readability. I've thought of using a utility method like this:
public static List<T> SingleItemList<T>( T value )
{
return (new List<T>( new T[] { value } ));
}
So I could do:
SingleItemList("title");
Is there a shorter / cleaner way?
Thanks.
Simply use this:
List<string> list = new List<string>() { "single value" };
You can even omit the () braces:
List<string> list = new List<string> { "single value" };
Update: of course this also works for more than one entry:
List<string> list = new List<string> { "value1", "value2", ... };
var list = new List<string>(1) { "hello" };
Very similar to what others have posted, except that it makes sure to only allocate space for the single item initially.
Of course, if you know you'll be adding a bunch of stuff later it may not be a good idea, but still worth mentioning once.
Michael's idea of using extension methods leads to something even simpler:
public static List<T> InList<T>(this T item)
{
return new List<T> { item };
}
So you could do this:
List<string> foo = "Hello".InList();
I'm not sure whether I like it or not, mind you...
A different answer to my earlier one, based on exposure to the Google Java Collections:
public static class Lists
{
public static List<T> Of<T>(T item)
{
return new List<T> { item };
}
}
Then:
List<string> x = Lists.Of("Hello");
I advise checking out the GJC - it's got lots of interesting stuff in. (Personally I'd ignore the "alpha" tag - it's only the open source version which is "alpha" and it's based on a very stable and heavily used internal API.)
new[] { "item" }.ToList();
It's shorter than
new List<string> { "item" };
and you don't have to specify the type.
Use an extension method with method chaining.
public static List<T> WithItems(this List<T> list, params T[] items)
{
list.AddRange(items);
return list;
}
This would let you do this:
List<string> strings = new List<string>().WithItems("Yes");
or
List<string> strings = new List<string>().WithItems("Yes", "No", "Maybe So");
Update
You can now use list initializers:
var strings = new List<string> { "This", "That", "The Other" };
See http://msdn.microsoft.com/en-us/library/bb384062(v=vs.90).aspx
Yet another way, found on "C#/.Net Little wonders" (unfortunately, the site doesn't exist anymore):
Enumerable.Repeat("value",1).ToList()
For a single item enumerable in java it would be Collections.singleton("string");
In c# this is going to be more efficient than a new List:
public class SingleEnumerator<T> : IEnumerable<T>
{
private readonly T m_Value;
public SingleEnumerator(T value)
{
m_Value = value;
}
public IEnumerator<T> GetEnumerator()
{
yield return m_Value;
}
IEnumerator IEnumerable.GetEnumerator()
{
yield return m_Value;
}
}
but is there a simpler way using the framework?
I've got this little function:
public static class CoreUtil
{
public static IEnumerable<T> ToEnumerable<T>(params T[] items)
{
return items;
}
}
Since it doesn't prescribe a concrete return type this is so generic that I use it all over the place. Your code would look like
CoreUtil.ToEnumerable("title").ToList();
But of course it also allows
CoreUtil.ToEnumerable("title1", "title2", "title3").ToArray();
I often use it in when I have to append/prepend one item to the output of a LINQ statement. For instance to add a blank item to a selection list:
CoreUtil.ToEnumerable("").Concat(context.TrialTypes.Select(t => t.Name))
Saves a few ToList() and Add statements.
(Late answer, but I stumbled upon this oldie and thought this could be helpful)
Try var
var s = new List<string> { "a", "bk", "ca", "d" };
You can also do
new List<string>() { "string here" };
I would just do
var list = new List<string> { "hello" };
Inspired by the other answers (and so I can pick it up whenever I need it!), but with naming/style aligned with F# (which has a standard singleton function per data structure*):
namespace System.Collections.Generic
{
public static class List
{
public static List<T> Singleton<T>(T value) => new List<T>(1) { value };
}
}
* except for ResizeArray itself of course, hence this question :)
In practice I actually name it Create to align with other helpers I define such as Tuple.Create, Lazy.Create[2], LazyTask.Create etc:
namespace System.Collections.Generic
{
public static class List
{
public static List<T> Create<T>(T value) => new List<T>(1) { value };
}
}
[2]
namespace System
{
public static class Lazy
{
public static Lazy<T> Create<T>(Func<T> factory) => new Lazy<T>(factory);
}
}
The declarations make it so easy now to do in C# 10.0 that I don't think theres a need for any helper. Just add the new(){} around any value you want to cast to a list.
List<string> values = new() { "single value" };
If someone landed on this page and trying to add object instead of string, then this worked for me.
new List<myObj> { new myObj{propertName=propstryValue }
, new myObj{propertName=propstryValue }, new myObj{propertName=propstryValue }
};
You need to create an inheritor from the List<> class
public class SingletonList<T> : List<T>
{
public SingletonList(T element) : base(1)
{
this.Add(element);
}
}
and you can use it instead of the base List<> class
var singletonList = new SingletonList<string>("Hello World!");

How to remove multiple objects in List by id?

I have a class as below
class MyClass
{
public string id { get; set; }
public string data { get; set; }
}
I have an array of ids I need to remove:
List<myClass> myObjArray = new List<myClass>;
myClass myObj1 = new myClass { id = "1", data = "aaa"};
myClass myObj2 = new myClass { id = "2", data = "bbb"};
myClass myObj3 = new myClass { id = "3", data = "ccc"};
myClass myObj4 = new myClass { id = "4", data = "ddd"};
myObjArray.Add(myObj1);
myObjArray.Add(myObj2);
myObjArray.Add(myObj3);
myObjArray.Add(myObj4);
string [] idToBeRemove = {"1", "3"};
Is there any method to remove the myObj in myObjArray where the id is in the idToBeRemove string?
List<T> has a method RemoveAll which will accomplish what you need. Unlike doing something like Where(...).ToList(), it will modify the existing list in place rather than create a new one.
myObjArray.RemoveAll(item => idToBeRemove.Contains(item.id));
Note that as your array of items to remove grows, you'll want to move to something more performant, such as a HashSet<T>, though with your current count of 2, it is not a pressing need.
#Richardissimo also offers a good suggestion in the comments to your question for when the main list itself grows, a Dictionary<K, V> could be useful. Again, not an immediate need with a small list, but something to keep in mind as it grows and if performance is an issue.
To remove from existing List you can use List.RemoveAll(Predicate):
myObjArray.RemoveAll(r => idToBeRemove.Contains(r.id));
To get result in new collection you can use Enumerable.Where and Enumerable.Contains:
var result = myObjArray.Where(m => !idToBeRemove.Contains(m.id)).ToList();
var result = myObjArray.Where(m => !idToBeRemove.Contains(m.id)).ToList();
foreach (var item in result)
{
myObjArray.Remove(item);
}
Use this to remove id:
myObjArray.RemoveAll(item => idToBeRemove.Contains(item.id));

Categories