remove all element except from given index number - c#

I have following list and how can I remove with linq all elements from given index number:
List<string> a = new List<string>();
a.Add("number1");
a.Add("number2");
a.Add("number3");
How can I remove all element just except element which is index number =2 using linq.

LINQ isn't about removing things - it's about querying.
You can call RemoveRange to remove a range of items from a list though. So:
a.RemoveRange(0, 2);
will leave just "number3".
Or you could create a new list as per dasblinkenlight's answer. If you can tell us more about what you're trying to achieve and why you think LINQ is the solution, we may be able to help you more.
EDIT: Okay, now we have clearer requirements, you can use LINQ:
var newList = a.Where((value, index) => index != 2)
.ToList();

Assume you have list of indices you want to keep, you can use Where with index to filter:
var indexList = new[] {2};
var result = a.Where((s, index) => indexList.Contains(index));

An equivalent operation to "remove everything but X" is "keep X". The simplest way to do it is constructing a new list with a single element at index 2, like this:
a = new List<string>{a[2]};

Although #dasblinkenlight's answer is the better option, here is the linq (or at least one iteration)
a.Where((item,index) => b1 == 2);
or to return a single string objects rather than an IEnumberable
a.Where((a1,b1) => b1 == 2).First();

Related

How to Filter a 2-dimensional List?

I'm trying to filter the following list:
List<List<int>> list = new List<List<int>>()
{
new List<int>(){1,2,3,4,5},
new List<int>(){6,7,5,4,5},
new List<int>(){1,3,3,222,1}
}
My filter condition should be: "include only odd numbers", so my list shouldn't have any even numbers after the filter is applied.
My Attempt:
list = list.Where(x => x.Where(y => y%2 == 1).ToList()).ToList()
Desired Output:
List<List<int>> list = new List<List<int>>()
{
new List<int>(){1,3,5},
new List<int>(){7,5,5},
new List<int>(){1,3,3,1}
}
I know how to use Linq on single-dimensional collections, but not sure how to make this one work.
Any ideas?
You may use the following:
list = list.Select(x => x.Where(i => i % 2 == 1).ToList())
.Where(x => x.Any())
.ToList();
Here, we're using Select() to iterate the elements of the outer list, then using Where() to filter the inner list. After that, we call Where() on the outer list to filter out empty inner lists. That last part is optional; feel free to remove it if you need to keep empty lists.
Note: As #Dmitry stated in the comments, it's probably better to use i % 2 != 0 if you want to keep negative odd numbers.

Lambda Function to find most popular word in a List C# [duplicate]

This question already has answers here:
How to Count Duplicates in List with LINQ
(7 answers)
Closed 2 years ago.
I currently have what I believe is a lambda function with C# (fairly new to coding & haven't used a lambda function before so go easy), which adds duplicate strings (From FilteredList) in a list and counts the number of occurrences and stores that value in count. I only want the most used word from the list which I've managed to do by the "groups.OrderBy()... etc) line, however I'm pretty sure that I've made this very complicated for myself and very inefficient. As well as by adding the dictionary and the key value pairs.
var groups =
from s in FilteredList
group s by s into g
// orderby g descending
select new
{
Stuff = g.Key,
Count = g.Count()
};
groups = groups.OrderBy(g => g.Count).Reverse().Take(1);
var dictionary = groups.ToDictionary(g => g.Stuff, g => g.Count);
foreach (KeyValuePair<string, int> kvp in dictionary)
{
Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value);
}
Would someone please either help me through this and explain a little bit of this too me or at least point me in the direction of some learning materials which may help me better understand this.
For extra info: The FilteredList comes from a large piece of external text, read into a List of strings (split by delimiters), minus a list of string stop words.
Also, if this is not a lambda function or I've got any of the info in here incorrect, please kindly correct me so I can fix the question to be more relevant & help me find an answer.
Thanks in advance.
Yes, I think you have overcomplicated it somewhat.. Assuming your list of words is like:
var words = new[] { "what's", "the", "most", "most", "most", "mentioned", "word", "word" };
You can get the most mentioned word with:
words.GroupBy(w => w).OrderByDescending(g => g.Count()).First().Key;
Of course, you'd probably want to assign it to a variable, and presentationally you might want to break it into multiple lines:
var mostFrequentWord = words
.GroupBy(w => w) //make a list of sublists of words, like a dictionary of word:list<word>
.OrderByDescending(g => g.Count()) //order by sublist count descending
.First() //take the first list:sublist
.Key; //take the word
The GroupBy produces a collection of IGroupings, which is like a Dictionary<string, List<string>>. It maps each word (the key of the dictionary) to a list of all the occurrences of that word. In my example data, the IGrouping with the Key of "most" will be mapped to a List<string> of {"most","most","most"} which has the highest count of elements at 3. If we OrderByDescending the grouping based on the Count() of each of the lists then take the First, we'll get the IGrouping with a Key of "most", so all we need to do to retrieve the actual word is pull the Key out
If the word is just one of the properties of a larger object, then you can .GroupBy(o => o.Word). If you want some other property from the IGrouping such as its first or last then you can take that instead of the Key, but bear in mind that the property you end up taking might be different each time unless you enforce ordering of the list inside the grouping
If you want to make this more efficient than you can install MoreLinq and use MaxBy; getting the Max word By the count of the lists means you can avoid a sort operation. You could also avoid LINQ and use a dictionary:
string[] words = new[] { "what", "is", "the", "most", "most", "most", "mentioned", "word", "word" };
var maxK = "";
var maxV = -1;
var d = new Dictionary<string, int>();
foreach(var w in words){
if(!d.ContainsKey(w))
d[w] = 0;
d[w]++;
if(d[w] > maxV){
maxK = w;
maxV = d[w];
}
}
Console.WriteLine(maxK);
This keeps a dictionary that counts words as it goes, and will be more efficient than the LINQ route as it needs only a single pass of the word list, plus the associated dictionary lookups in contrast to "convert wordlist to list of sublists, sort list of sublists by sublist count, take first list item"
This should work:
var mostPopular = groups
.GroupBy(item => new {item.Stuff, item.Count})
.Select(g=> g.OrderByDescending(x=> x.Count).FirstOrDefault())
.ToList();
OrderByDescending along with .First() combines your usage of OrderBy, Reverse() and Take.
First part is a Linq operation to read the groups from the FilteredList.
var groups =
from s in FilteredList
group s by s into g
// orderby g descending
select new
{
Stuff = g.Key,
Count = g.Count()
};
The Lambda usage starts when the => signal is used. Basically means it's going to be computed at run time and an object of that type/format is to be created.
Example on your code:
groups = groups.OrderBy(g => g.Count).Reverse().Take(1);
Reading this, it is going to have an object 'g' that represents the elements on 'groups' with a property 'Count'. Being a list, it allows the 'Reverse' to be applied and the 'Take' to get the first element only.
As for documentation, best to search inside Stack Overflow, please check these links:
C# Lambda expressions: Why should I use them? - StackOverflow
Lambda Expressions in C# - external
Using a Lambda Expression Over a List in C# - external
Second step: if the data is coming from an external source and there are no performance issues, you can leave the code to refactor onwards. A more detail data analysis needs to be made to ensure another algorithm works.

Auto-incrementing a generic list using LINQ in C#

Is there a good way to provide an "auto-increment" style index column (from 1..x) when projecting items using LINQ?
As a basic example, I'm looking for the index column below to go from 1 to the number of items in list.
var items = from s1 in list
select new BrowsingSessionItemModel { Id = s1.Id, Index = 0 };
Iterating through the list would be the easy option but I was wondering if there was a better way to do this?
You can't do this with LINQ expressions. You could use the following .Select extension method though:
var items = list.Select((x, index) => new BrowsingSessionItemModel {
Id = x.Id,
Index = index
});
You can use the overload of Select which takes the provides the index to the projection as well:
var items = list.Select((value, index) => new BrowsingSessionItemModel {
Id = value.Id,
Index = index
});
Note that there is no query expression support for this overload. If you're actually fetching the values from a database (it's not clear whether list is really a List<T>) you should probably make sure you have an appropriate ordering, as otherwise the results are somewhat arbitrary.

return elements from List considering an alphabet rule

So I'm trying to build a function that receives as a parameter a List of 5 elements, this list is of the string type, and the result that I'm after follows this logic:
List:
List<string> lista= new List<string>();
lista.Add("Movel");
lista.Add("ONU");
lista.Add("Pata");
lista.Add("Tela");
lista.Add("Plasticos");
I need to return only the elements where the last letter is superior to the first following alphabetical order, in this case, only "ONU" and "Plasticos" would be returned.
I'm rather new to C#, in fact, I'm just new to programming overall, but in the small knowledge I've accumulated, I honestly don't know where to go with this, any help would be grand.
Theres probably regex ways you can do this or something, but you can probably do this with a Linq expression of some sort e.g.
IEnumerable<string> temp = from str in lista
let last = str.ToLower().Last()
let first = str.ToLower().First()
where last > first
select str;
Would give you the answers you seek I think, but that's probably a pretty inefficient way to do it if you need a quick algorithm.
return lista.Where(s => { s = s.ToLower(); return s[0] < s[s.Length-1] });
Try:
List<string> listb = lista.FindAll(s => String.Compare(s.Substring(s.Length - 1), s.Substring(0, 1)) == 1).ToList();
I could come up with this
List<string> filtered = lista.FindAll(s => char.ToLowerInvariant(s[s.Length - 1]) > char.ToLowerInvariant(s[0])).ToList();
My result:
var result = lista.Where(x => x.ToLower()[0] < x.ToLower()[x.Length - 1]).ToList();

Lambda expression for getting items from list according to indexes

Is it possible to get objects from a list according to their indexes at one shot? For example I have a List<string> alist. I have an integer List List<int> indexes which has indexes. Is it possible to get a result list from the original list which equals the indexes in the array.
I am looking for something like List<string> resultlist = alist.GetItems(items.indexin(indexes)) (that's just my imagination, not the actual syntax-sorry)
Something like this should work:
var result = indexes.Select(i => alist[i]).ToList();
Of course, I recommend you make it a bit more robust.
var result = alist.Where((theString, theIndex) => indexes.Contains(theIndex));
indexes.Select<int, string>(i => alist[i]).ToList<string>();

Categories