Update IList data - c#

I have used two IList object. In first list, it contains 10 records and the second contains 5 records. Now I want to update the first IList with second IList data.
foreach (ObjList newlist in New)
{
ObjList list = ExtList.FirstOrDefault(x => x.Id == newlist.Id);
if (list!= null)
{
ExtList.Remove(list);
ExtList.Add(newlist);
}
}
I tried the above. But the added object appended at the end of the list. So sort order changed. I need it in the same existing order.
Updated
I tried the sorting, but it is not sorted.
ExtList.OrderBy(x => x.Id);

You can try using IList.Insert() to add new item at the index of to-be-replaced item, so that you can keep the list in it's original order :
ObjList list = ExtList.FirstOrDefault(x => x.Id == newlist.Id);
if (list!= null)
{
var position = ExtList.IndexOf(list);
ExtList.Insert(position, newlist);
ExtList.Remove(list);
}

If you want to keep the order after update, you can :
ExtList=(from e in ExtList
join n in New
on e.Id equals n.Id into left
from n in left.DefaultIfEmpty()
select new /*Class Name */
{
Id=e.Id,
Name=n==null?e.Name:n.Name
}).ToList();

You should use ExtList.IndexOf instead ExtList.FirstOrDefault.
And then use ExtList.Insert to given index instead ExtList.Add

Related

Filtering a list and removing unwanted data C#

I have a list of users for a timespan, for arguments sake let's say a month. So in that list certain users do not meet the criteria I want for a certain objective so I want to filter out the list and display the filtered out data into another list. So how I replicated the list was as follows:
List<tblList1> List1 = new XPQuery<tblList1>(session)
.Where(w => w.UserCode != null).ToList();
I then use a foreach loop to go through this list to compare the data to my criteria and then add them to the new list which is working perfectly. The problem I now have is to delete the data I took from the first list. I tried the following in a new method which I created:
public void DeleteData(Session session)
{
List<tblList1> List1= new XPQuery<tblList1>(session)
.Where(w => w.UserID != null).ToList();
List<tblList2> List2= new XPQuery<tblList2>(session)
.Where(w => w.UserID!= null).ToList();
List1.RemoveAll(w => w.UserID == List2.Any(e => e.UserID== w.UserID));
}
So in the end I want to remove all the data in list1 so that we can view the deleted data in list2. Any help would be appreciated if I can just get the RemoveAll LINQ statement correct as the current line does not work and I am unsure of how to handle this in LINQ.
As far as I can see from comments:
I want to take List1 {1, 2, 3} compare them to criteria and see that {
2 } does not meet that criteria and add that in List2. Then delete { 2
} from List1
I can't see any need in Linq at all. Let's fill both Lists in parallel:
List<tblList1> List1 = new List<tblList1>();
//TODO: please, check types; it seems that it should be List<tblList1> List2
List<tblList2> List2 = new List<tblList2>();
foreach (var item in new XPQuery<tblList1>(session).Where(w => w.UserID != null)) {
if (YourCriteriaHere)
List1.Add(item); // <- Criteria met: add to List1
else
List2.Add(item); // <- Doesn't meet: "delete" from (just not add to) List1 into List2
}
You can just use LINQ Where to filter your list, and then Except to get unfiltered values:
List<Item> all = ...; // your original list
List<Item> matching = all.Where(x => IsMatching(x)).ToList(); // IsMatching is any filtering logic
List<Item> notMatching = all.Except(matching).ToList();

LINQ List overwrites previous value instead of setting new one

I have a LINQ query which outputs ToList it works fine other than the fact each time it's run it updates the original record instead of creating a new one.
On every run through this code the data.EventID changes so I'd like every record to appear in the list.
The code:
foreach(var data in vehicleqry)
{
bool inUK = boundryChecker.IsLongLatInUK((double)data.declatfloat, (double)data.declongfloat);
if (inUK == true)
{
var qryevent = (from e in db.events
where e.eventID == data.EventID
select new
{
e.eventID,
e.sysdatetime,
e.vehicleID
}).ToList();
}
{
I also have a list with the eventIDs in if I can use this to query the list?
I think what you actually want is to only run a single query instead of looping around. You can do this by making use of the Contains method:
var vehicleqry = ...;
// Get all of the individual event IDs for entries that are "inUK"
var vehicleEventIds = vehicleqry
.Where(ve => boundryChecker
.IsLongLatInUK((double)ve.declatfloat, (double)ve.declongfloat)
.Select(ve => ve.EventID);
// Get all the matching events
var qryevent = (from e in db.events
where vehicleEventIds.Contains(e.eventID)
select new
{
e.eventID,
e.sysdatetime,
e.vehicleID
}).ToList();

Adding list to a new list

Take if from the top. have a list that I return MyTableList.
var MyTableList = List<ExportDto>(List);
this tableList returns ID's that is needed to select another level from the same table.
IEnumerable<int?> rowselect = MyTableList.Where(n => n.ID != null)
.Select(n => n.ID);
this provides me with a list of ID's are then returned;
I use a
foreach (var item in rowselect)
getnewlist = getnewinfo.GetSinglerows(item.Value);
The main problem is for me Adding this new list and merging it with MyTableList.
Use List<T>.AddRange Method as following:
MyTableList.AddRange(getnewlist );

Select top N elements and remember occurence's order

I have a requirement to select top N elements of related products from a big list of products.
So far, I have below code and it works perfectly.
class Product
{
public string Name;
public double Rating;
public List<Product> RelatedProducts;
public List<Product> GetTopRelatedProducts(int N)
{
var relatedSet = new HashSet<Product>();
var relatedListQueue = new Queue<List<Product>>();
if (RelatedProducts != null && RelatedProducts.Count > 0)
relatedListQueue.Enqueue(RelatedProducts);
while (relatedListQueue.Count > 0)
{
var relatedList = relatedListQueue.Dequeue();
foreach (var product in relatedList)
{
if (product != this && relatedSet.Add(product) && product.RelatedProducts != null && product.RelatedProducts.Count > 0)
relatedListQueue.Enqueue(product.RelatedProducts);
}
}
return relatedSet.OrderByDescending(x => x.Rating).Take(N).OrderBy(/*How to order by occurrence here? */).ToList();
}
}
Now, I want GetTopRelatedProducts method to remember the occurrence order of top N products. First added product to the HashSet will be at the begining of the returned List.
For example, if I have this scenario:
//...
relatedSet.Add(new Product(){Name="A", Rating=3});
relatedSet.Add(new Product(){Name="B", Rating=4});
relatedSet.Add(new Product(){Name="C", Rating=5});
//...
and if N = 2, the method should return : B,C instead of C,B because B was added first to the HashSet.
So I changed the return statement in the method to:
var relatedSetCopy = relatedSet.ToList();
return (from p in relatedSet.OrderByDescending(x => x.Rate).Take(N)
join c in relatedSetCopy on p.Name equals c.Name
let index = relatedSetCopy.IndexOf(c)
orderby index
select p).ToList();
Basically, I use LINQ Join to re-order the list in the same way it was before the ordering on Rating.
I want to do it this way because first added product has more similarity with selected product than others.
I have two questions here:
Is there a better way to re-order the returned list?
Is there a better design to handle relation between products? (I was thinking about implementing a tree structure. So object navigation and retrieval will be faster)
Is there a better way to re-order the returned list?
You can simply Intersect the relatedSet with the top N related reordered set because Intersect yields the items based on their order in the first sequence.
So instead of
return relatedSet.OrderByDescending(x => x.Rating).Take(N).ToList();
you would use
return relatedSet.Intersect(relatedSet.OrderByDescending(x => x.Rating).Take(N)).ToList();

How to find current index of your list / array in a changing list?

I have a list of lets say 10 items on the first call:
var myList = GetMyList();
okay now I get the item I want from this list:
myList.FirstOrDefault(x => x.Id == id);
Now I go to the web page and do stuff.
Now I am back: The list Could have changed by this point if anything was deactivated through a rest call in my API. (I rebuild the current list in the constructor)
public OneItemFromMyList Get(int id)
{
//Here I need the next item in the list after the one with the above Id
}
So how do I get that one. I do not want to repeat one that I retrieved before and I don't want to move outside of the list so I would need to start over if I am on the last position.
Any Suggestions?
To get an item immediately after the one with the specific id, do this:
var nextItem = myList.SkipWhile(x => x.Id != id).Take(2).LastOrDefault();
Note that this may not produce an item, if either of the following is true:
The item with x.Id == id is not there, or
The item with x.Id == id is the last item in the list.
I think this will work for you:
var nextId =
myList
.SkipWhile(x => x != id) //skip until x == id
.Skip(1) // but I don't want x == id so skip one more
.Concat(myList) // but item could be removed or I hit the end so restart
.First(); // the first item is the one I want!

Categories