arraylist with object type - c#

hi i using arraylist and storing simple object array in that , my sample code snipt
ArrayList rows = new ArrayList();
object[] objs = new object[3];
objs[0] = 1;
objs[1] = "dilip";
objs[2] = 27;
rows.Add(objs);
objs = new object[3];
objs[0] = 2;
objs[1] = "lucky";
objs[2] = 42;
rows.Add(objs);
objs = new object[3];
objs[0] = 3;
objs[1] = "user";
objs[2] = 46;
rows.Add(objs);
objs = new object[3];
objs[0] = 4;
objs[1] = "testing";
objs[2] = 76;
rows.Add(objs);
objs = new object[3];
objs[0] = 5;
objs[1] = "trying";
objs[2] = 44;
rows.Add(objs);
How can i apply asc or desc sorting on any index of object
for example sorting based on name which index 1 or sorting based on age which index 2 ..
please provide any suggestion .
Thanks ..

Most of LINQ methods will work with a strongly typed IEnumerable<T> interface.
Use OfType method like this rows.OfType<object[]>().OrderBy(x => x[1])
Though the way you approach your data structures will quickly make the code unmaintainable. You'd better consider using classes to reflect your data.

You need to have comparer to sort your ArrayList type. In your case it would look something like this:
public class MyComparer : IComparer
{
int IComparer.Compare(Object x, Object y)
{
int sortingIndex = 1;
var xUnbox = x as object[];
var yUnbox = y as object[];
return ((new CaseInsensitiveComparer()).Compare(yUnbox[sortingIndex], xUnbox[sortingIndex]));
}
}
Having this, you can now sort your ArrayList:
var comparer = new MyComparer();
rows.Sort(comparer);
foreach (object[] line in rows)
{
Console.WriteLine(line[1]);
}
This example would sort your ArrayList by index 1.
Although I would highly recommend using strongly typed collection, like List<YourType> instead, since then you could just Linq order that.

Is there a reason you could not use List<object[]> instead of using ArrayList?
For example:
List<object[]> rows = new List<object[]>();
object[] objs = new object[3];
objs[0] = 1;
objs[1] = "dilip";
objs[2] = 27;
rows.Add(objs);
var query = rows.Where(r => (string)r[1] == "dilip");
You could then do all your various sorting, etc.
var query = rows
.OrderBy(r => (int)r[0])
.OrderBy(r => (string)r[1])
.OrderByDescending(r => (int)r[2]);

Related

C# How to make a list out of IEnumerable

I'm currently playing with TvDbSharper (https://github.com/HristoKolev/TvDbSharper) and i have a question about IEnumerable.
What i'm trying to do is get all the Id for a given series and then add the result in a listView.
This code gives me the first Id in the list:
const int SeriesId = 78804;
var tasks = new List<Task<TvDbResponse<BasicEpisode[]>>>();
var firstResponse = await client.Series.GetEpisodesAsync(SeriesId, 1);
for (int i = 2; i <= firstResponse.Links.Last; i++)
{
tasks.Add(client.Series.GetEpisodesAsync(SeriesId, i));
}
var results = await Task.WhenAll(tasks);
var episodes = firstResponse.Data.Concat(results.SelectMany(x => x.Data));
epsListview.View = View.Details;
epsListview.Columns.Add("Episode", 100);
string[] arr = new string[4];
ListViewItem itm;
arr[0] = episodes.First().Id.ToString();
itm = new ListViewItem(arr);
epsListview.Items.Add(itm);
but what i want is to make a new line in the epsListview for each id available.
I never used IEnumerable and i'm still very novice using c#, i've been stuck with this problem for over a week now. can anyone help me with this ?
Thanks!!
It looks like you're wanting to build an array of IDs from an IEnumerable of episodes, and add that array to a single ListViewItem. This should do that.
string[] arr = episodes.Select(episode => episode.Id.ToString()).ToArray()
ListViewItem itm = new ListViewItem(arr);
epsListview.Items.Add(itm);

Sum on a dynamic list that has ExpandoObject as items

I have a dynamic list with ExpandoObject as items :
List<dynamic> list = new List<dynamic>();
foreach (...)
{
var dynamicObject = new ExpandoObject() as IDictionary<string, Object>;
...
list.Add(dynamicObject);
}
How can I use .Sum() on a dynamic list ? I know the names of the properties
of that list , but Sum() does not take a string as argument .
Thanks
Assuming you have list like this:
var list = new List<dynamic>
{
new ExpandoObject(),
new ExpandoObject(),
new ExpandoObject(),
};
list[0].Foo = 1;
list[1].Foo = 2;
list[2].Foo = 3;
you can use ExpandoObject's properties as regular properties, if their names are known at compile-time:
var sum1 = list
.Sum(item => item.Foo);
or use dictionary syntax, if property names are known at run-time only:
var sum2 = list
.Sum(item => (int)((IDictionary<string, object>)item)["Foo"]);
You can use Sum(Func<TSource, int> selector)
For you example :
var values = new int[] {1, 2, 3, 4, 5};
List<dynamic> list = new List<dynamic>();
foreach (var value in values)
{
var dynamicObject = new ExpandoObject() as IDictionary<string, Object>;
dynamicObject[value.ToString()] = value;
list.Add(dynamicObject);
}
// Kind of ugly as cast but otherwise it has trouble to find the Count property
var result = list.Sum(x => (x as IDictionary<string, Object>).Count);
Console.WriteLine("Result: {0}", result);
Console.ReadLine();
To my mind you could try this :
var listSum = list.Sum(item => item.GetType().GetProperty("propertyName").GetValue());
I called list the list on which you want to call the Sum method.
Let me know if the result is what you want.

is it possible to get the linq for the following?

SQL Query
SELECT *
FROM tblOrders
WHERE CustomerId in (3455,4423,7655,1000)
LINQ Query
?
Say, I have an Array of IDs, then how do I search?
int[4] _ids;
_ids[0]=3455
_ids[1]=4423
_ids[2]=7655
_ids[3]=1000
var _orders = (from o in tblOrders
where (o.CustomerId in _ids[])
select o);
Above code is just for the example sake, I know it's wrong. But, is this possible?
No, it is not.
Try this one:
var _orders = from o in tblOrders
where _ids.Contains(o.CustomerId)
select o;
The keyword in you used, it is used for other purpose in C#. It is not like IN in SQL.
It is used in foreach statements. For instance:
foreach(var _id in _ids)
Console.WriteLine(_id);
Also, it is used as a generic modifier, for generic type parameters. For more documentation on the latter, please have a look here.
You can use the Contains method of the _ids array.
var _orders = from o in tblOrders
where _ids.Contains(o.CustomerId)
select o;
Use code as given below
List<Orders> lstOrders = new List<Orders>();
Orders objOrders;
for (int index = 1; index <= 10; index++)
{
objOrders = new Orders();
objOrders.OrderID = index;
objOrders.Order = "Order_" + index.ToString();
objOrders.CustomerID = index;
lstOrders.Add(objOrders);
}
int[] _customers = { 1, 2, 3, 4, 5 };
List<Orders> lstFilteredOrders = new List<Orders>();
lstFilteredOrders.AddRange(lstOrders.FindAll(x => _customers.Any(y =>y == x.CustomerID)));

Compare Two non related entity collection in Linq C#

I want to compare two non related entities by using linq.
e.g -
Entity A
Id Name
1 A
2 B
3 C
4 D
Entity B
Id Name
1 B
2 C
Result I should get
A, D
From the above two collection I want to compare Entity B with Entity A by using the Name property and find out the records which are not available in Entity B.
Any help will be appreciated with some sample code.
Regards
You can use the Except extension method of LINQ. Quote from MSDN Documentation...
Produces the set difference of two sequences by using the default equality comparer to compare values.
Sample Code
int[] a = { 1, 2, 3, 4, 5 };
int[] b = { 4,5,6,7 };
var c = a.Except(b);
Result
1,2,3
Note
Because you are working with a custom object (a class) you will need to implement an equality comparer that compares items by the Name property. Example of custom equality comparer...
public class CustomComparer : IEqualityComparer<CustomObject>
{
public bool Equals(CustomObject x, CustomObject y)
{
return x.Name.Equals(y);
}
public int GetHashCode(CustomObject obj)
{
return obj.Name.GetHashCode();
}
}
Then you can use this custom equality comparer in an overload of the Except extension method, assumming a and b are of type CustomObject...
var c = a.Except(b, new CustomComparer());
The advantage is re-usability, especially if you are spreading this call to Except all over your project. Then,if you need to change your entity(custom object) you only have make changes in the custom equality comparer
var result = entityAs.Where(a => !entityBs.Any(b => b.Name == a.Name)).ToList();
Create a Class
class MyClass
{
public int Id {get; set;}
public string Name {get; set;}
}
Create List1
List<MyCLass> li1 = new List<MyCLass>();
MyCLass o1 = new MyClass();
o1.Id = 1;
o1.Name = "A";
li1.Add(o1);
o1 = new
o1.Id = 2;
o1.Name = "B";
li1.Add(o1);
o1 = new new MyClass();
o1.Id = 3;
o1.Name = "C";
li1.Add(o1);
o1 = new new MyClass();
o1.Id = 4;
o1.Name = "D";
li1.Add(o1);
Create List2
List<MyCLass> li2 = new List<MyCLass>();
o1 = new new MyClass();
o1.Id = 1;
o1.Name = "B";
li2.Add(o1);
o1 = new new MyClass();
o1.Id = 2;
o1.Name = "C";
li2.Add(o1);
o1 = new new MyClass();
o1.Id = 3;
o1.Name = "D";
li2.Add(o1);
Select only Selected items which you want to compare from List1
List<string> SelectedName = li1.Select(s => s.Name).ToList();
FinalList1 only Get those Item which are in List2
var FinalList = li2.Where(w => SelectedName.Contains(w.Name)).ToList();
/// or
FinalList2 only Get those Item which are not in List2
var FinalList2 = li2.Where(w => !SelectedName.Contains(w.Name)).ToList();

Linq Select Array values at specific indexes

I have this method:
public void Foo(double[] values1, double[] values2, int[] indexes)
{
var values1AtIndexes = new List<double>();
var values1NotAtIndexes = new List<double>();
var values2AtIndexes = new List<double>();
var values2NotAtIndexes = new List<double>();
for (int i = 0; i < values1.Length; i++)
{
if (indexes.Contains(i))
{
values1AtIndexes.Add(values1[i]);
values2AtIndexes.Add(values2[i]);
}
else
{
values1NotAtIndexes.Add(values1[i]);
values2NotAtIndexes.Add(values2[i]);
}
}
}
And I was wondering if there is a LINQ-way to this?
It could look like that (not looking at perf).
So I'm not sure that it's shorter, or easier to understand.
values1AtIndexes = values1.Where((m, index) => indexes.Contains(index)).ToList();
values2AtIndexes = values2.Where((m, index) => indexes.Contains(index)).ToList();
//alternative
values1AtIndexes = indexes.Select(m => values1[m]).ToList();
values1AtIndexes = indexes.Select(m => values2[m]).ToList();
//might be wrong if your lists contain duplicated values
values1NotAtIndexes = values1.Except(values1AtIndexes).ToList();
values2NotAtIndexes = values2.Except(values2AtIndexes).ToList();
As you pointed, Except might give you wrong results if you have duplicates.
So if you know you can have duplicates, you should rather do
values1NotAtIndexes = values1.Where((m, index) => !indexes.Contains(index)).ToList();

Categories

Resources