MVC .NET OrWhere Query - c#

I want to perform a query on a list of words.
string[] words = {"word1", "word2", "word3"}
In my database I have a list of tracks with artist and titles. I want to concatenate all the queries with OrWhere conditions.
This is what I have for the moment :
var word;
var queryTracks;
for (int i = 0; i < words.Length; i++)
{
word = words[i];
queryTracks = db.Tracks.Where(c => c.Title.Contains(word) || c.Artist.Contains(word));
}
// all found, put all that into a list
var filteredTracks = queryTracks.ToList();
I already tried with the .Concat() method like this :
var word = words[0];
var queryTracks = db.Tracks.Where(c => c.Title.Contains(word) || c.Artist.Contains(word));;
for (int i = 1; i < words.Length; i++)
{
word = words[i];
queryTracks = queryTracks.Concat(db.Tracks.Where(c => c.Title.Contains(word) || c.Artist.Contains(word)));
}
But it didn't work... I just want to have all the tracks with word1, word2 and word3. Can I make a big query and then put it into a list or do I have to make list1, list2 and list3 and concatenate them ?

You can use a single query
string[] words = {"word1", "word2", "word3"}
IEnumerable<Track> tracks = db.Tracks.Where(c => words.Contains(c.Title) || words.Contains(c.Artist));

Related

Split and then Joining the String step by step - C# Linq

Here is my string:
www.stackoverflow.com/questions/ask/user/end
I split it with / into a list of separated words:myString.Split('/').ToList()
Output:
www.stackoverflow.com
questions
ask
user
end
and I need to rejoin the string to get a list like this:
www.stackoverflow.com
www.stackoverflow.com/questions
www.stackoverflow.com/questions/ask
www.stackoverflow.com/questions/ask/user
www.stackoverflow.com/questions/ask/user/end
I think about linq aggregate but it seems it is not suitable here. I want to do this all through linq
You can try iterating over it with foreach
var splitted = "www.stackoverflow.com/questions/ask/user/end".Split('/').ToList();
string full = "";
foreach (var part in splitted)
{
full=$"{full}/{part}"
Console.Write(full);
}
Or use linq:
var splitted = "www.stackoverflow.com/questions/ask/user/end".Split('/').ToList();
var list = splitted.Select((x, i) => string.Join("/", a.Take(i + 1)));
Linq with side effect:
string prior = null;
var result = "www.stackoverflow.com/questions/ask/user/end"
.Split('/')
.Select(item => prior == null
? prior = item
: prior += "/" + item)
.ToList();
Let's print it out
Console.WriteLine(string.Join(Environment.NewLine, result));
Outcome:
www.stackoverflow.com
www.stackoverflow.com/questions
www.stackoverflow.com/questions/ask
www.stackoverflow.com/questions/ask/user
www.stackoverflow.com/questions/ask/user/end
Linq without side effects ;)
Enumerable.Aggregate can be used here if we use List<T> as a result.
var raw = "www.stackoverflow.com/questions/ask/user/end";
var actual =
raw.Split('/')
.Aggregate(new List<string>(),
(list, word) =>
{
var combined = list.Any() ? $"{list.Last()}/{word}" : word;
list.Add(combined);
return list;
});
without Linq write below code,
var str = "www.stackoverflow.com/questions/ask/user/end";
string[] full = str.Split('/');
string Result = string.Empty;
for (int i = 0; i < full.Length; i++)
{
Console.WriteLine(full[i]);
}
for (int i = 0; i < full.Length; i++)
{
if (i == 0)
{
Result = full[i];
}
else
{
Result += "/" + full[i];
}
Console.WriteLine(Result);
}

C# use Linq method instead of for loop

I have a string array and a for loop to add items to list.
Here is my code:
//customers table :
// Firstname, Lastname, Age, BrowserName, Date
string[] browsers = {"chrome", "Firefox", "Edge"}
var users = db.customers.ToList();
list<string> names = new List<string>();
for(var i = 0; i < browsers.lenght; i++) {
names.Add(users.where(x => x.BrowserName == browsers[i]).FirstName);
}
Is there any way to use Linq method or something else instead of for ?
Instead of
for(var i = 0; i < browsers.lenght; i++) {
names.Add(users.where(x => x.BrowserName == browsers[i]).FirstName);
}
Use this
names = users.Where(x => browsers.Contains(x.BrowserName)).Select(y => y.FirstName).ToList();
You can do it by foreach like the following:
browsers.ToList().Foreach(x => users.where(y => y.BrowserName == x).ToList().Foreach(z => names.Add(z.FirstName)))

Splitting an string into a string array.?

I am facing a problem while executing a sql query in C#.The sql query throws an error when the string contains more than 1000 enteries in the IN CLAUSE .The string has more than 1000 substrings each seperated by ','.
I want to split the string into string array each containing 999 strings seperated by ','.
or
How can i find the nth occurence of ',' in a string.
Pull the string from SQL server into a DataSet using a utilities code like
string strResult = String.Empty;
using (SqlCommand cmd = new SqlCommand())
{
cmd.Connection = conn;
cmd.CommandText = strSQL;
strResult = cmd.ExecuteScalar().ToString();
}
Get the returned string from SQL Server
Split the string on the ','
string[] strResultArr = strResult.Split(',');
then to get the nth string that is seperated by ',' (I think this is what you mean by "How can i find the nth occurence of ',' in a string." use
int n = someInt;
string nthEntry = strResultArr[someInt - 1];
I hope this helps.
You could use a regular expression and the Index property of the Match class:
// Long string of 2000 elements, seperated by ','
var s = String.Join(",", Enumerable.Range(0,2000).Select (e => e.ToString()));
// find all ',' and use '.Index' property to find the position in the string
// to find the first occurence, n has to be 0, etc. etc.
var nth_position = Regex.Matches(s, ",")[n].Index;
To create an array of strings of your requiered size, you could split your string and use LINQ's GroupBy to partition the result, and then joining the resulting groups together:
var result = s.Split(',').Select((x, i) => new {Group = i/1000, Value = x})
.GroupBy(item => item.Group, g => g.Value)
.Select(g => String.Join(",", g));
result now contains two strings, each with 1000 comma seperated elements.
How's this:
int groupSize = 1000;
string[] parts = s.Split(',');
int numGroups = parts.Length / groupSize + (parts.Length % groupSize != 0 ? 1 : 0);
List<string[]> Groups = new List<string[]>();
for (int i = 0; i < numGroups; i++)
{
Groups.Add(parts.Skip(i * groupSize).Take(groupSize).ToArray());
}
Maybe something like this:
string line = "1,2,3,4";
var splitted = line.Split(new[] {','}).Select((x, i) => new {
Element = x,
Index = i
})
.GroupBy(x => x.Index / 1000)
.Select(x => x.Select(y => y.Element).ToList())
.ToList();
After this you should just String.Join each IList<string>.
//initial string of 10000 entries divided by commas
string s = string.Join(", ", Enumerable.Range(0, 10000));
//an array of entries, from the original string
var ss = s.Split(',');
//auxiliary index
int index = 0;
//divide into groups by 1000 entries
var words = ss.GroupBy(w =>
{
try
{
return index / 1000;
}
finally
{
++index;
}
})//join groups into "words"
.Select(g => string.Join(",", g));
//print each word
foreach (var word in words)
Console.WriteLine(word);
Or you may find the indeces in the string and split it into substrings afterwards:
string s = string.Join(", ", Enumerable.Range(0, 100));
int index = 0;
var indeces =
Enumerable.Range(0, s.Length - 1).Where(i =>
{
if (s[i] == ',')
{
if (index < 9)
++index;
else
{
index = 0;
return true;
}
}
return false;
}).ToList();
Console.WriteLine(s.Substring(0, indeces[0]));
for (int i = 0; i < indeces.Count - 1; i++)
{
Console.WriteLine(s.Substring(indeces[i], indeces[i + 1] - indeces[i]));
}
However, I would think over, if it was possible to work with the entries before they are combined into one string. And probably think, if it was possible to prevent the necessity to make a query which needs that great list to pass into the IN statement.
string foo = "a,b,c";
string [] foos = foo.Split(new char [] {','});
foreach(var item in foos)
{
Console.WriteLine(item);
}

Extract all occurrences of specific characters from strings

I have something like this in my code.
mystring.Split(new[]{"/","*"}, StringSplitOptions.RemoveEmptyEntries);
however, what I actually want is to separate mystring into two arrays, one holding the separated items above, and the other array to hold the delimiters above in the order they appear in the string.
I could use .IndexOf to continue searching until I extract all of them, but somehow I think this will be redundant. Is there a way to do this in .NET? If possible I want to avoid LINQ.
Thanks.
Something like:
var separators = new char[] { '/', '*' };
var words = new List<string>();
var delimiters = new List<string>();
var idx = source.IndexOfAny(separators);
var prevIdx = 0;
while (idx > -1)
{
if (idx - prevIdx > 0)
words.Add(source.Substring(prevIdx, idx - prevIdx));
prevIdx = idx + 1;
delimiters.Add(source.Substring(idx, 1));
idx = source.IndexOfAny(separators, idx + 1);
}
If I understand the questioner correctly, he wants the actual separated items as well as the delimiters.
I think the following code will work:
List<string> SeparatedItems = new List<string>();
List<string> Delimiters = new List<string>();
string sTestString = "mytest/string*isthis**and not/this";
string sSeparatedItemString = String.Empty;
foreach(char c in sTestString) {
if(c == '/' || c == '*') {
Delimiters.Add(c.ToString());
if(sSeparatedItemString != String.Empty) {
SeparatedItems.Add(sSeparatedItemString);
sSeparatedItemString = String.Empty;
}
}
else {
sSeparatedItemString += c.ToString();
}
}
if(sSeparatedItemString != String.Empty) {
SeparatedItems.Add(sSeparatedItemString);
}
Try this:
var items = new List<string>();
var delimiters = new List<string>();
items.AddRange(Regex.Split(text, #"(?<=/)|(?=/)|(?<=\*)|(?=\*)"));
for (int i = 0; i < items.Count; )
{
string item = items[i];
if (item == "*" || item == "/")
{
delimiters.Add(item);
items.RemoveAt(i);
}
else if (item == "")
{
items.RemoveAt(i);
}
else
{
i++;
}
}
You could consider a Regex expression using named groups. Try a nested named group. The outer including capturing the separator and the inner capturing the content only.
Since you're running in .NET 2.0, I'd say using IndexOf is one of the most straight forward ways to solve the problem:
public static int CountOccurences(string input, string pattern)
{
int count = 0;
int i = 0;
while (i = input.IndexOf(pattern, i) != -1)
count++;
return count;
}
The solution Rob Smyth suggests would also work, but I find this the easiest and most understandable one.

C# String Pattern Matching

I have 2 lists of strings in C# showing the players who have joined and left a particular game. I'm trying to attempt to determine who is still in the game by matching both lists and eliminating the entries of those who have left the game. Please suggest a easy and pain free algorithm to go about doing this. My current code is as follows
string input = inputTextBox.Text;
string[] lines = input.Split(new string[] {"\r\n", "\n"}, StringSplitOptions.None);
List<string> filteredinput = new List<string>();
List<string> joinedlog = new List<string>();
List<string> leftlog = new List<string>();
for (int i = 0; i<lines.Length; i++)
{
if (lines[i].Contains("your game!"))
filteredinput.Add(lines[i]);
}
for (int i =0; i<filteredinput.Count; i++)
{
if (filteredinput[i].Contains("joined"))
joinedlog.Add(filteredinput[i]);
else if (filteredinput[i].Contains("left"))
leftlog.Add(filteredinput[i]);
}
Here is some sample input :
{SheIsSoScrewed}[Ping:|] has joined your game!.
{AngeLa_Yoyo}[Ping:X] has joined your game!.
{SheIsSoScrewed} has left your game!(4).
Are you asking how to get your two lists, or how to find the current players after you've already got the two lists?
The second part can be done with Linq....
List<string> joinedGame;
List<string> leftGame;
List<string> currentInGame
= joinedGame.Where(x => !leftGame.Contains(x)).ToList();
EDIT In response to your comment, having read your question again then obviously the above won't work because you are building your lists in a weird way.
You are storing the whole string in the list, e.g. user_1 has left the game, what you should probably be doing is just storing the user name. If you correct this then the above code does exactly what you want.
A full example:
var input = new List<string>()
{
"user_1 has joined the game",
"user_2 has joined the game",
"user_1 has left the game",
"user_3 has joined the game"
};
var joined = new List<string>();
var left = new List<string>();
foreach(string s in input)
{
var idx = s.IndexOf(" has joined the game");
if (idx > -1)
{
joined.Add(s.Substring(0, idx));
continue;
}
idx = s.IndexOf(" has left the game");
if (idx > -1)
{
left.Add(s.Substring(0, idx));
}
}
var current = joined.Where(x => !left.Contains(x)).ToList();
foreach(string user in current)
{
Console.WriteLine(user + " is still in the game");
}
Intersect and Except are your friends.
Also, if this is the sole purpose of the lists, consider using something like HashSet instead.
How about using List.Find() ?
Link 1 here
Link 2 here
use linq and regex:
var join=new Regex("joined.*?your game");
var joinLog = (from l in lines where join.IsMatch(join) select l).ToList();
var left=new Regex("left.*?your game");
var leftLog = (from l in lines where left.IsMatch(join) select l).ToList();
First you need to extract the player names so you can calculate the difference:
var join=new Regex("{(.*)}[.*joined.*?your game");
var joinedNames = filteredinput.Select(l => join.Match(l)).Where(m => m.Success).Select(m => m.Groups[1]).Distinct();
var left=new Regex("{(.*)}[.*left.*?your game");
var leftNames = filteredinput.Select(l => left.Match(l)).Where(m => m.Success).Select(m => m.Groups[1]).Distinct();
Now calculate the difference:
var playersStillInGame = joinedNames.Except(leftNames);
string input = inputTextBox.Text;
string[] lines = input.Split(new string[] {"\r\n", "\n"}, StringSplitOptions.None);
Regex joinedLeft = new Regex(#"\{([^{}]*)}.*? has (joined|left) your game!");
HashSet<string> inGame = new HashSet<string>();
foreach (string line in lines)
{
Match match = joinedLeft.Match(line);
if (!match.Success)
continue;
string name = match.Groups[1].Value;
string inOrOut = match.Groups[2].Value;
if (inOrOut == "joined")
inGame.Add(name);
else
inGame.Remove(name);
}

Categories