Split list based on value without groups - c#

I want to split my list by value, but I don't need group the result,
this is my list :
var source = new List<Car>() {
new Car() { ID = 1, Model = "Model A" },
new Car() { ID = 2, Model = "Model B" },
new Car() { ID = 3, Model = "Model B" },
new Car() { ID = 4, Model = "Model B" },
new Car() { ID = 5, Model = "Model A" },
new Car() { ID = 6, Model = "Model A" }
};
var result = GetListOfAdjacentCarsOfSameModel();
I want the resulting list to look like this:
- Model A
- ID = 1, Model = "Model A"
- Model B
- ID = 2, Model = "Model B"
- ID = 3, Model = "Model B"
- ID = 4, Model = "Model B"
- Model A
- ID = 5, Model = "Model A"
- ID = 6, Model = "Model A"

I suggest a simple loop:
var result = new List<List<Car>>();
foreach (var item in source)
if (result.Count <= 0 || result[result.Count - 1][0].Model != item.Model)
result.Add(new List<Car>() {item}); // Create a new group, add item to it
else
result[result.Count - 1].Add(item); // Add item into the last group

public class Car
{
public int ID { get; set; }
public string Model { get; set; }
}
public class Result
{
public string Model { get; set; }
public int Count { get; set; }
}
var source = new List<Car>();
source.Add(new Car { ID = 1, Model = "Model A" });
source.Add(new Car { ID = 1, Model = "Model B" });
source.Add(new Car { ID = 1, Model = "Model B" });
source.Add(new Car { ID = 1, Model = "Model B" });
source.Add(new Car { ID = 1, Model = "Model A" });
source.Add(new Car { ID = 1, Model = "Model A" });
var result = new List<Result>();
if (source.Any())
{
string model = source[0].Model;
int count = 0;
foreach (var car in source)
{
if (car.Model == model)
{
count++;
}
else
{
result.Add(new Result { Model = model, Count = count });
model = car.Model;
count = 1;
}
}
result.Add(new Result { Model = model, Count = count });
}
foreach (var r in result)
{
Console.WriteLine(r.Model + " - " + r.Count);
}

I'm struggling with finding a simple way to do this, but you can always do it iteratively:
var source = new List<string>() {
"Model A",
"Model B",
"Model B",
"Model B",
"Model A",
"Model A"
};
string lastModel = null;
List<string> currentList = new List<string>();
var result = new List<List<string>>();
foreach (var model in source)
{
if (lastModel != null && model != lastModel)
{
result.Add(currentList);
currentList = new List<string>();
}
currentList.Add(model);
lastModel = model;
}
if (currentList.Any()) {
result.Add(currentList);
}
Now, it's easy to wrap that code in an extension method you can use on your car class:
var source = new List<Car>() {
new Car { Model = "Model A" },
new Car { Model = "Model B" },
new Car { Model = "Model B" },
new Car { Model = "Model B" },
new Car { Model = "Model A" },
new Car { Model = "Model A" }
};
var result = source.CollectAdjacentWithSameModel();
// elsewhere
public static class EnumerableExtensions
{
public static IEnumerable<IEnumerable<Car>> CollectAdjacentWithSameModel(this IEnumerable<Car> source)
{
var lastModel = default(Car);
List<Car> currentList = new List<Car>();
var result = new List<List<Car>>();
foreach (var model in source)
{
if (lastModel != null && model.Model != lastModel.Model)
{
result.Add(currentList);
currentList = new List<Car>();
}
currentList.Add(model);
lastModel = model;
}
if (currentList.Any())
{
result.Add(currentList);
}
return result;
}
}
public class Car {
public string Model { get; set; }
}

Related

Remove from a list that has a list within it based on integer list

I have a list that basically look like this...
public class Area
{
public int Id { get; set; }
public string Name { get; set; }
public List<ZipCodeAdresses> ListOfIncludedDestinations { get; set; }
}
public class ZipCodeAdresses
{
public int AreaId { get; set; }
public List<Person> AdressList { get; set; }
}
public class Person
{
public string MottagarNamn { get; set; }
public string Street { get; set; }
}
var intListToRemove = new List<int>(){2,3};
var list = new List<Area>();
var subList = new List<ZipCodeAdresses>();
var personList = new List<Person>
{
new Person() {MottagarNamn = "User 1"},
new Person() {MottagarNamn = "User 2"}
};
subList.Add(new ZipCodeAdresses(){AdressList = personList , AreaId = 1});
personList = new List<Person>
{
new Person() {MottagarNamn = "User 3"},
new Person() {MottagarNamn = "User 4"}
};
subList.Add(new ZipCodeAdresses() { AdressList = personList, AreaId = 2 });
list.Add(new Area(){Name = "List A", ListOfIncludedDestinations = subList});
subList = new List<ZipCodeAdresses>();
personList = new List<Person>
{
new Person() {MottagarNamn = "User 5"},
new Person() {MottagarNamn = "User 6"}
};
subList.Add(new ZipCodeAdresses() { AdressList = personList, AreaId = 3 });
personList = new List<Person>
{
new Person() {MottagarNamn = "User 7"},
new Person() {MottagarNamn = "User 8"}
};
subList.Add(new ZipCodeAdresses() { AdressList = personList, AreaId = 4 });
list.Add(new Area() { Name = "List B", ListOfIncludedDestinations = subList });
I need to be able to remove from the list ListOfIncludedDestinations where AreaId is equal to any integer in intListToRemove which in this example is 2 and 3?
List<T> contains a method RemoveAll, that removes all entries that fulfill a certain condition. In your case it is:
foreach(var entry in list)
{
entry.ListOfIncludedDestinations.RemoveAll(x => intListToRemove.Contains(x.AreaId));
}
This loops through your list, and for every entry it removes all entries in ListOfIncludedDestinations that have an AreadId which is in intListToRemove.
Online demo: https://dotnetfiddle.net/ialnPb
You should add this sample code to remove them from the list :
foreach (var i in list)
i.ListOfIncludedDestinations.RemoveAll(o => intListToRemove.Contains(o.AreaId));

How to add an element to a property of type List <T>?

I use the classes Form1.cs,MockProduct.cs and Product.cs.
To add a new entry, I use the method:
public partial class Form1: Form
    {
        public Form1 ()
        {
            InitializeComponent ();
        }
 
    
        public void AddItem ()
        {
            Product product = new Product ()
            {
                ID = 4,
                Name = "Name_4",
                Description = "Description_4"
            };
 
            MockProduct.ProductList.Add (product);
 
            var v = MockProduct.ProductList;
        }
 
    }
 
I am checking a record using the expression MockProduct.ProductList.Count.
Result: MockProduct.ProductList.Count = 3.
In other words, the entry is not added.
 
Question.
1. How to add an element to a property of type List ?
2. Does my code have an error?
 
Picture-1
MockProduct.cs
static class MockProduct
{
static List<Product> productList;
public static List<Product> ProductList
{
get
{
return productList = new List<Product>
{
new Product {ID = 1, Name = "Name_1", Description = "Description_1"},
new Product {ID = 2, Name = "Name_2", Description = "Description_2"},
new Product {ID = 3, Name = "Name_3", Description = "Description_3"},
};
}
set
{
productList = value;
}
}
}
Product.cs
public class Product
{
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
Every time, when you call getter of ProductList property, you'll create and initialize a new instance of productList field (using new operator), therefore you always getting ProductList.Count equals 3.
Try to move this logic outside the property and initialize productList only once, when declaring it
static List<Product> productList = new List<Product>
{
new Product {ID = 1, Name = "Name_1", Description = "Description_1"},
new Product {ID = 2, Name = "Name_2", Description = "Description_2"},
new Product {ID = 3, Name = "Name_3", Description = "Description_3"},
};
public static List<Product> ProductList
{
get
{
return productList;
}
set
{
productList = value;
}
}
If you want a initial value for your list you could instantiate your list only the first time you access it:
get
{
if (productList == null)
{
productList = new List<Product>
{
new Product {ID = 1, Name = "Name_1", Description = "Description_1"},
new Product {ID = 2, Name = "Name_2", Description = "Description_2"},
new Product {ID = 3, Name = "Name_3", Description = "Description_3"},
};
}
return productList;
}
set
{
productList = value;
}
How to add an element to a property of type List ?
You are using the right method:
ProductList.Add (product);
Does my code have an error?
Yes, the getter for ProductList returns always a new list.
Remove this code from MockProduct class:
public static List<Product> ProductList
{
get
{
return productList = new List<Product>
{
new Product {ID = 1, Name = "Name_1", Description = "Description_1"},
new Product {ID = 2, Name = "Name_2", Description = "Description_2"},
new Product {ID = 3, Name = "Name_3", Description = "Description_3"},
};
}
set
{
productList = value;
}
}

Store Data In a Generic List and use Linq

Model.cs contains the Data of the User which is stored in a list type Now We have to fetch all those students whose age is more than 25.
public class Model
{
public int Age { get; set; }
public string Name { get; set; }
public string Sports { get; set; }
List<Model> objModels = new List<Model>() {
new Model { Name = "Manish", Age = 27, Sports = "Cricket" },
new Model { Name = "Rajan", Age = 25, Sports = "FootBall" },
new Model { Name = "Prashant", Age = 25, Sports = "Kabaddi" },
new Model { Name = "Garima", Age = 24, Sports = "Ludo" },
new Model { Name = "Neha", Age = 25, Sports = "Carom" }
};
}
ModelController.cs
public class ModelController : Controller
{
// GET: Model
public ActionResult Index()
{
List<Model> objModel = new List<Model>();
var query = from models in objModel select models;
foreach(var item in query.ToList())
{
objModel.Add(
new Model
{
Name = item.Name.ToString(),
Age = int.Parse(item.Age.ToString()),
Sports = item.Sports.ToString()
});
}
return View(objModel);
}
}
But The object is always empty because it is not fetching the data from the model class.
Hi have you tried to do:
public class Model
{
public int Age { get; set; }
public string Name { get; set; }
public string Sports { get; set; }
public List<Model> Models
{
get
{
return objModels;
}
set {
Model = value;
}
}
List<Model> objModels = new List<Model>() {
new Model { Name = "Manish", Age = 27, Sports = "Cricket" },
new Model { Name = "Rajan", Age = 25, Sports = "FootBall" },
new Model { Name = "Prashant", Age = 25, Sports = "Kabaddi" },
new Model { Name = "Garima", Age = 24, Sports = "Ludo" },
new Model { Name = "Neha", Age = 25, Sports = "Carom" }
};
}
And then use it in your controller as :
List<Model> newModelList=new List<Model>();
Model objModel = Model;
var query = from models in objModel.Models where models.age<25 select models;
foreach (var item in query.ToList())
{
newModelList.Add(
new Model
{
Name = item.Name.ToString(),
Age = int.Parse(item.Age.ToString()),
Sports = item.Sports.ToString()
});
}
return View(newModelList);
DBCOntext.cs - a new class for Handeling The Data.
public class DBContext
{
List<Model> objModel = new List<Model>();
public List<Model> GetData()
{
objModel.Add(new Model
{
Name = "Manish",Age = 27,Sports = "Cricket"
});
objModel.Add(new Model
{
Name = "Rajan",Age = 25,Sports = "FootBall"
});
objModel.Add(new Model
{
Name = "Prashant", Age = 25,Sports = "Kabaddi"
});
objModel.Add(new Model
{
Name = "Garima", Age = 24,Sports = "Ludo"
});
objModel.Add(new Model
{
Name = "Neha",Age = 25,Sports = "Carom"
});
return objModel;
}
}
And Controller class to access all the DBContext Data which can be used to send the data to the View
List<Model> objModel = new List<Model>();
// GET: Model
public ActionResult Index()
{
DBContext db = new DBContext();
var query = from models in db.GetData() where models.Age>25 orderby models.Age select models;
foreach (var item in query.ToList())
{
objModel.Add(
new Model
{
Name = item.Name.ToString(),
Age = int.Parse(item.Age.ToString()),
Sports = item.Sports.ToString()
});
}
return View(objModel);
}

Linq to entities remove from list

I want to remove items from a list of entities, when there is a concidence from a list (id). I have written this code, but I am guessing there is a better way to do it, and improve performance.
Here is my code:
List<int> toRemove; //includes the ids of the entities to be removed
if (people.Count > 1)
people.RemoveAll(x => people.Any(y => y != x && toRemove.Contains(x.ID)));
else
people.RemoveAll(x => toRemove.Contains(x.ID));
Given a list of people, for example:
var people = new List<Person>
{
new Person { ID = 1, Name = "Fred1" },
new Person { ID = 2, Name = "Fred2" },
new Person { ID = 3, Name = "Fred3" },
new Person { ID = 4, Name = "Fred4" },
new Person { ID = 5, Name = "Fred5" },
new Person { ID = 6, Name = "Fred6" },
new Person { ID = 7, Name = "Fred7" },
new Person { ID = 8, Name = "Fred8" },
new Person { ID = 9, Name = "Fred9" },
new Person { ID = 10, Name = "Fred10" }
};
And a list of IDs to remove:
List<int> toRemove = new List<int> { 3, 4, 5 };
You can remove the unwanted entries like this:
people = people.Where(p => !toRemove.Contains(p.ID)).ToList();
Oh, and for completeness, here's a Person class to complete the example!
public class Person
{
public int ID { get; set; }
public string Name { get; set; }
}
And to show it working:
https://ideone.com/ERP3rk

compare two list and return not matching items using linq

i have a two list
List<Sent> SentList;
List<Messages> MsgList;
both have the same property called MsgID;
MsgList SentList
MsgID Content MsgID Content Stauts
1 aaa 1 aaa 0
2 bbb 3 ccc 0
3 ccc
4 ddd
5 eee
i want to compare the MsgID in Msglist with the sentlist and need items which are not in the sent list using linq
Result
MsgID Content
2 bbb
4 ddd
5 eee
You could do something like:
HashSet<int> sentIDs = new HashSet<int>(SentList.Select(s => s.MsgID));
var results = MsgList.Where(m => !sentIDs.Contains(m.MsgID));
This will return all messages in MsgList which don't have a matching ID in SentList.
The naive approach:
MsgList.Where(x => !SentList.Any(y => y.MsgID == x.MsgID))
Be aware this will take up to m*n operations as it compares every MsgID in SentList to each in MsgList ("up to" because it will short-circuit when it does happen to match).
Well, you already have good answers, but they're most Lambda. A more LINQ approach would be like
var NotSentMessages =
from msg in MsgList
where !SentList.Any(x => x.MsgID == msg.MsgID)
select msg;
You can do like this,this is the quickest process
Var result = MsgList.Except(MsgList.Where(o => SentList.Select(s => s.MsgID).ToList().Contains(o.MsgID))).ToList();
This will give you expected output.
You can do something like
var notSent = MsgSent.Except(MsgList, MsgIdEqualityComparer);
You will need to provide a custom equality comparer as outlined on MSDN
http://msdn.microsoft.com/en-us/library/bb336390.aspx
Simply have that equality comparer base equality only on MsgID property of each respective type. Since the equality comparer compares two instances of the same type, you would need to define an interface or common base type that both Sent and Messages implement that has a MsgID property.
Try,
public class Sent
{
public int MsgID;
public string Content;
public int Status;
}
public class Messages
{
public int MsgID;
public string Content;
}
List<Sent> SentList = new List<Sent>() { new Sent() { MsgID = 1, Content = "aaa", Status = 0 }, new Sent() { MsgID = 3, Content = "ccc", Status = 0 } };
List<Messages> MsgList = new List<Messages>() { new Messages() { MsgID = 1, Content = "aaa" }, new Messages() { MsgID = 2, Content = "bbb" }, new Messages() { MsgID = 3, Content = "ccc" }, new Messages() { MsgID = 4, Content = "ddd" }, new Messages() { MsgID = 5, Content = "eee" }};
int [] sentMsgIDs = SentList.Select(v => v.MsgID).ToArray();
List<Messages> result1 = MsgList.Where(o => !sentMsgIDs.Contains(o.MsgID)).ToList<Messages>();
Hope it should help.
In .NET 6 you can take advantage of .ExceptBy(), which lets you define which property of the first list to compare the items in the second list by:
List<Message> result = messages
.ExceptBy(sentList.Select(msg => msg.MsgID), msg => msg.MsgID)
.ToList();
messages is the first list, whereas a collection of the MsgID properties from sentList is the second list.
Example fiddle here.
Note:
.ExceptBy() produces the set difference between the two collections --> only distinct values will be in the resulting collection. This means that if messages contains the same value more than once (e.g. { "aaa", "bbb", "ccc", "ddd", "ddd", "eee" }), any duplicates will be removed in the resulting collection (--> { "bbb", "ddd", "eee" }).
As an extension method
public static IEnumerable<TSource> AreNotEqual<TSource, TKey, TTarget>(this IEnumerable<TSource> source, Func<TSource, TKey> sourceKeySelector, IEnumerable<TTarget> target, Func<TTarget, TKey> targetKeySelector)
{
var targetValues = new HashSet<TKey>(target.Select(targetKeySelector));
return source.Where(sourceValue => targetValues.Contains(sourceKeySelector(sourceValue)) == false);
}
eg.
public class Customer
{
public int CustomerId { get; set; }
}
public class OtherCustomer
{
public int Id { get; set; }
}
var customers = new List<Customer>()
{
new Customer() { CustomerId = 1 },
new Customer() { CustomerId = 2 }
};
var others = new List<OtherCustomer>()
{
new OtherCustomer() { Id = 2 },
new OtherCustomer() { Id = 3 }
};
var result = customers.AreNotEqual(customer => customer.CustomerId, others, other => other.Id).ToList();
Debug.Assert(result.Count == 1);
Debug.Assert(result[0].CustomerId == 1);
List<Person> persons1 = new List<Person>
{
new Person {Id = 1, Name = "Person 1"},
new Person {Id = 2, Name = "Person 2"},
new Person {Id = 3, Name = "Person 3"},
new Person {Id = 4, Name = "Person 4"}
};
List<Person> persons2 = new List<Person>
{
new Person {Id = 1, Name = "Person 1"},
new Person {Id = 2, Name = "Person 2"},
new Person {Id = 3, Name = "Person 3"},
new Person {Id = 4, Name = "Person 4"},
new Person {Id = 5, Name = "Person 5"},
new Person {Id = 6, Name = "Person 6"},
new Person {Id = 7, Name = "Person 7"}
};
var output = (from ps1 in persons1
from ps2 in persons2
where ps1.Id == ps2.Id
select ps2.Name).ToList();
Person class
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
If u wanna Select items of List from 2nd list:
MainList.Where(p => 2ndlist.Contains(p.columns from MainList )).ToList();
make single list and
var result = list.GroupBy(x => x.BillId).Where(x => x.Count() == 1).Select(x => x.First());
List<Car> cars = new List<Car>() { new Car() { Name = "Ford", Year = 1892, Website = "www.ford.us" },
new Car() { Name = "Jaguar", Year = 1892, Website = "www.jaguar.co.uk" },
new Car() { Name = "Honda", Year = 1892, Website = "www.honda.jp"} };
List<Factory> factories = new List<Factory>() { new Factory() { Name = "Ferrari", Website = "www.ferrari.it" },
new Factory() { Name = "Jaguar", Website = "www.jaguar.co.uk" },
new Factory() { Name = "BMW", Website = "www.bmw.de"} };
foreach (Car car in cars.Where(c => !factories.Any(f => f.Name == c.Name))) {
lblDebug.Text += car.Name;
}

Categories

Resources