I have a list of objects I want to reorder. The order is determined in a string.
(I hope my current code explains better than the text)
List<DataObject> objects = GetDataObjectsFromDatabase();
string order = "1,3,2";
List<DataObject> orderedObjects = new List<DataObject>
foreach(string index in order.Split(',')
{
orderedObjects.Add(objects.FirstOrDefault(x => x.id == index));
}
Is there a single Linq statement or a better way to do this?
Here is example of ordering list based on another list in linq:
List<OBJ> Test = new List<OBJ>();
Test.Add(new OBJ(1));
Test.Add(new OBJ(2));
string Order = "1,2,3";
List<string> OrderBy = Order.Split(new char[] { ',' }).ToList();
Test = Test.OrderBy(x => OrderBy.IndexOf(x.Field1.ToString())).ToList();
Console.ReadKey();
Assuming that x.Field1 is your ID (or whatever field you want to sort by).
Provided that .Select() will happen in order:
var orderedObjects = order.Split(',').Select(int.Parse).Select(index => objects.FirstOrDefault(obj => obj.id == index).ToList();
var data = order.Split(',').ToList();
Related
From a given list of strings I need to use LINQ to generate a new sequence of strings, where each string consists of the first and last characters of the corresponding string in the original list.
Example:
stringList: new[] { "ehgrtthrehrehrehre", "fjjgoerugrjgrehg", "jgnjirgbrnigeheruwqqeughweirjewew" },
expected: new[] { "ee", "fg", "jw" });
list2 = stringList.Select(e => {e = "" + e[0] + e[e.Length - 1]; return e; }).ToList();
This is what I've tried, it works, but I need to use LINQ to solve the problem and I'm not sure how to adapt my solution.
just for the sake of completeness here is a version using Zip
var stringList = new string [] { "ehgrtthrehrehrehre", "fjjgoerugrjgrehg", "jgnjirgbrnigeheruwqqeughweirjewew" };
var result = stringList.Zip(stringList, (first, last) => $"{first.First()}{last.Last()}");
As mentioned in the comment that Select is already part of LINQ, you can use this code.var output = arr.Select(x => new string(new char[] { x.First(), x.Last() })).ToList();
Here you go:
var newList = stringList.Select(e => $"{e[0]}{e[e.Length - 1]}").ToList();
Approach with LINQ and String.Remove():
string[] input = new[] { "ehgrtthrehrehrehre", "fjjgoerugrjgrehg", "jgnjirgbrnigeheruwqqeughweirjewew" };
string[] result = input.Select(x => x.Remove(1, x.Length - 2)).ToArray();
I'm constructing a linq query that will check is a string in the DB contains any of the strings in a list of strings.
Something like.
query = query.Where(x => x.tags
.Contains(--any of the items in my list of strings--));
I'd also like to know how many of the items in the list were matched.
Any help would be appreciated.
Update: I should have mentioned that tags is a string not a list. And I am adding on a couple more wheres that are not related to tags before the query actually runs. This is running against entity framework.
EDIT: This answer assumed that tags was a collection of strings...
It sounds like you might want:
var list = new List<string> { ... };
var query = query.Where(x => x.tags.Any(tag => list.Contains(tag));
Or:
var list = new List<string> { ... };
var query = query.Where(x => x.tags.Intersect(list).Any());
(If this is using LINQ to SQL or EF, you may find one works but the other doesn't. In just LINQ to Objects, both should work.)
To get the count, you'd need something like:
var result = query.Select(x => new { x, count = x.tags.Count(tag => list.Contains(tag)) })
.Where(pair => pair.count != 0);
Then each element of result is a pair of x (the item) and count (the number of matching tags).
I've done something like this before:
var myList = new List<string>();
myList.Add("One");
myList.Add("Two");
var matches = query.Where(x => myList.Any(y => x.tags.Contains(y)));
like this:
List<string> list = new List<string>();
list.Add("One");
list.Add("Two");
var result = query.Where(x => list.Contains(x.tags));
I am not quite sure from your question if x.tags is a string or list, if it is a list Jon Skeet's answer is correct. If I understand you correctly though x.tags is a string of strings. If so then the solution is:
list.Any(x => x.tags.IndexOf(x) > -1)
to count them do
list.Count(x => x.tags.IndexOf(x) > -1)
var t = new List<string> { "a", "b", "c" };
var y = "a b d";
var res = y.Count(x => t.Contains(x.ToString()));
I faced a similar problem recently and here's how I managed to work it out:
var list = [list of strings];
if (list != null && list.Any())
{
queryable = queryable.Where(x => x.tags != null);
var tagQueries = new List<IQueryable<WhateverTheDbModelIs>>();
foreach (var element in list)
{
tagQueries.Add(queryable.Where(x => x.tags.Contains(element)));
}
IQueryable<WhateverTheDbModelIs> query = tagQueries.FirstOrDefault();
foreach (var tagQuery in tagQueries)
{
query = query.Union(tagQuery);
}
queryable = queryable.Intersect(query);
}
probably not the best option but something a less experienced developer can understand and use
I have a linq list obtained from database in my Model. Now I have a string array obtained from my controller. I want to construct a statement
pseudo-code
List<object> objlist = db.objects.tolist();
string[] strarray; // obtained from a long code.
var k = objlist.Where(u => u.somecol == strarray[0] || u.somecol == strarray[1]........strarray[n]).toList();
I am little bit confused how to accomplish this since my strarray[] is variable length and can contain upto 1000 words.
You can check if an array contains some item using the Array.IndexOf<T> Method:
bool strarrayContainsX = Array.IndexOf<string>(strarray, "X") >= 0;
However, I'd recommend you use a HashSet<string> instead of a string array for anything more than a few items. The HashSet<T> Class provides a Contains Method to check if a set contains some item:
HashSet<string> strset = new HashSet<string>(strarray);
bool strsetContainsX = strset.Contains("X");
The resulting query then looks like this:
var k = objlist.Where(u => strset.Contains(u.somecol)).ToList();
Use Contains:
var k = objlist.Where(u => strarray.Contains(u.somecol)).toList();
Try this:
List<object> objlist = db.objects.tolist();
string[] strarray; // obtained from a long code.
var k = objlist.Where(u => strarray.Contains(u.somecol)).toList();
var k = objlist.Where(u => strarray.Any(x=>x == u.somecol)).ToList();
I'm new to linq. I have a string having the following format
code:description;code2:description2;code3:description3... etc.
Records are separated with ; character and each record has 2 fields separated with : character.
I'm writing a linq query to extract a list of objects having as fields code and description.
I have written the following query which seems to produce correct results, but I was wondering if there is a better or more correct way to do it.
var objects =
from objString in recsString.Split(';')
let obj = objString.Split(':')
select new {
Code = obj[0].Trim(),
Description = obj[1].Trim()
};
That's perfectly fine, the only observation I would make though is that you remove empty entries by using the StringSplitOptions:
var objects =
from objString in recsString.Split(';', StringSplitOptions.RemoveEmptyEntries)
let obj = objString.Split(':', StringSplitOptions.RemoveEmptyEntries)
select new {
Code = obj[0].Trim(),
Description = obj[1].Trim()
};
If you think that there could be missing information, you could also be extra safe and null check the results:
var objects =
from objString in recsString.Split(';', StringSplitOptions.RemoveEmptyEntries)
let obj = objString.Split(':', StringSplitOptions.RemoveEmptyEntries)
select new {
Code = obj.Any() ? obj[0].Trim() : string.Empty,
Description = obj.Count > 1 ? obj[1].Trim() : string.Empty
};
What you're doing is just fine, here is how you'd write it using lambdas:
string objString = "code:description;code2:description2;code3:description3";
Dictionary<string, string> results =
objString.Split(';')
.Select(x => x.Split(':'))
.ToDictionary(key => key[0], value => value[1]);
// And now you have a nice little dictionary
foreach (var r in results)
Console.WriteLine("{0}:{1}",r.Key, r.Value);
Or of course:
var results = objString.Split(';')
.Select(x => x.Split(':'))
.Select(x => new {Code = x[0], Description = x[1]});
foreach (var r in results)
Console.WriteLine("{0}:{1}",r.Code, r.Description);
This seems like it would be easy enough
var orx = gg.Where(x=>x.ProductAttributes.Any (pa =>pa.AttributeId == "home"));
returns gg when product attributes has a value of "home"
I need it to return where and gg has product attribute values from an array
i.e.
var orx = gg.Where(x=>x.ProductAttributes.Any (pa =>pa.AttributeId in "home,work"));
what about...
string[] values = new string[] { "home", "work" };
var orx = gg.Where(x => x.ProductAttributes.Any(pa => values.Contains(pa.AttributeId));
or even "home,work".Contains(pa.AttributeId) should work, if your list is as reliable as your example. (I by no mean recommend this unless you can ensure that AttributeId will not be a substring of any of the list words.. such as "me")
Using Enumerable.Contains():
var orx = gg.Where(x => x.ProductAttributes
.Any(pa =>
array.Containspa(pa.AttributeId));
var orx = gg.Where(x => x.ProductAttributes
.Any(pa =>
"home, work".Split(',').Contains(pa.AttributeId));