I have three string list, the purpose is combine these list to a single string with separator.
List<string> list1=new List<string>{"A","B","C"};
List<string> list2=new List<string>{"=","<", ">"};
List<string> list3=new List<string>{"1","2","3"};
The final output is like following:
A=1 AND B<2 AND C>3
Is there any easy way to generate the final string? I used for loop, but it seems to be ugly. I know C# string has Join method to combine an array with separator. How to combine multiple arrays with separator?
Below is my code:
StringBuilder str = new StringBuilder();
for(int i=0; i< list1.count; i++)
{
str.AppendFormat("{0}{1}{2} AND ", list1[i], list2[i], list3[i]);
}
str.Length = str.Length -5;
string final = str.ToString();
Use Linq Zip() twice:
string result = string.Join(" AND ", list1.Zip(list2, (l1, l2) => l1 + l2).Zip(list3, (l2, l3) => l2 + l3));
https://dotnetfiddle.net/ZYlejS
You could use a combination of string.Join and linq:
string.Join(" AND ", list1.Select((e1, idx) => $"{e1} {list2[idx]} {list3[idx]}"));
You could use one of overloads EquiZip() in MoreLINQ:
var res = string.Join(" AND ", list1.EquiZip(list2, list3, (x, y, z) => x + y + z));
You could also use a combination of string.Join along with Enumerable.Range like so:
string result = string.Join(" AND ", Enumerable.Range(0, Math.Min(list1.Count,
Math.Min(list2.Count, list3.Count)))
.Select(i => $"{list1[i]} {list2[i]} {list3[i]}"));
if the lists are guaranteed to have the same size then it can be reduced to:
string b = string.Join(" AND ", Enumerable.Range(0, list1.Count)
.Select(i => $"{list1[i]} {list2[i]} {list3[i]}"));
Related
I have this code
var myBuilder = new StringBuilder();
foreach (var item in myList)
{
myBuilder.Append(item.Number).Append(" - ").Append(item.SecondNumber).Append(", ");
}
var text = myBuilder;
and using that I'm getting this text
AAA08 - BB08, AAA09 - BB09, AAA09 - BB10,
myList returns this:
{ Number = "AAA08", SecondNumber = "BB08" }
{ Number = "AAA09", SecondNumber = "BB09" }
{ Number = "AAA09", SecondNumber = "BB10" }
How can I concatenate it to string to display this:
AAA08 - BB08; AAA09 - BB09, BB10
I can do replace , to ; but can't get how to group these Numberto display only one and each SecondNumber right to him
You can do this with Linq and string.Join
var grouped = myList
.GroupBy(x => x.Number)
.Select(g => g.Key + " - " + string.Join(", ", g.Select(x => x.SecondNumber)))
var text = string.Join("; ", grouped);
You can use GroupBy and String.Join:
var groupedNumbers= myList
.GroupBy(x => x.Number)
.Select(g => $"{g.Key} - {String.Join(", ", g.Select(x => x.SecondNumber))}");
string result = String.Join("; ", groupedNumbers);
I'm using string interpolation which is a C#6 feature, if you aren't using it replace $"{g.Key}..." with String.Format("{0}...", g.Key, ..).
When you get Number, iterate through myList to find all instances of Number, then get each corresponding SecondNumber and append it to your string.
Before building final string you probably would need to group your array first with this code:
var groupedList = myList.GroupBy(x => x.Number)
and later use that grouped list to get proper string:
foreach (var item in groupedList)
{
myBuilder.Append(item.Number).Append(" - ").Append(item.Select(x => x.SecondNumber).Join(", ")).Append("; ");
}
I want to find the duplicates for a given string, I tried for collections, It is working fine, but i don't know how to do it for a string.
Here is the code I tried for collections,
string name = "this is a a program program";
string[] arr = name.Split(' ');
var myList = new List<string>();
var duplicates = new List<string>();
foreach(string res in arr)
{
if (!myList.Contains(res))
{
myList.Add(res);
}
else
{
duplicates.Add(res);
}
}
foreach(string result in duplicates)
{
Console.WriteLine(result);
}
Console.ReadLine();
But I want to find the duplicates for the below string and to store it in an array. How to do that?
eg:- string aa = "elements";
In the above string i want to find the duplicate characters and store it in an array
Can anyone help me?
Linq solution:
string name = "this is a a program program";
String[] result = name.Split(' ')
.GroupBy(word => word)
.Where(chunk => chunk.Count() > 1)
.Select(chunk => chunk.Key)
.ToArray();
Console.Write(String.Join(Environment.NewLine, result));
The same princicple for duplicate characters within a string:
String source = "elements";
Char[] result = source
.GroupBy(c => c)
.Where(chunk => chunk.Count() > 1)
.Select(chunk => chunk.Key)
.ToArray();
// result = ['e']
Console.Write(String.Join(Environment.NewLine, result));
string name = "elements";
var myList = new List<char>();
var duplicates = new List<char>();
foreach (char res in name)
{
if (!myList.Contains(res))
{
myList.Add(res);
}
else if (!duplicates.Contains(res))
{
duplicates.Add(res);
}
}
foreach (char result in duplicates)
{
Console.WriteLine(result);
}
Console.ReadLine();
string is an array of chars. So, you can use your collection approach.
But, I would reccomend typed HashSet. Just load it with string and you'll get array of chars without duplicates, with preserved order.
take a look:
string s = "aaabbcdaaee";
HashSet<char> hash = new HashSet<char>(s);
HashSet<char> hashDup = new HashSet<char>();
foreach (var c in s)
if (hash.Contains(c))
hash.Remove(c);
else
hashDup.Add(c);
foreach (var x in hashDup)
Console.WriteLine(x);
Console.ReadKey();
Instead of a List<> i'd use a HashSet<> because it doesn't allow duplicates and Add returns false in that case. It's more efficient. I'd also use a Dictionary<TKey,Tvalue> instead of the list to track the count of each char:
string text = "elements";
var duplicates = new HashSet<char>();
var duplicateCounts = new Dictionary<char, int>();
foreach (char c in text)
{
int charCount = 0;
bool isDuplicate = duplicateCounts.TryGetValue(c, out charCount);
duplicateCounts[c] = ++charCount;
if (isDuplicate)
duplicates.Add(c);
}
Now you have all unique duplicate chars in the HashSet and the count of each unique char in the dictionary. In this example the set only contains e because it's three times in the string.
So you could output it in the following way:
foreach(char dup in duplicates)
Console.WriteLine("Duplicate char {0} appears {1} times in the text."
, dup
, duplicateCounts[dup]);
For what it's worth, here's a LINQ one-liner which also creates a Dictionary that only contains the duplicate chars and their count:
Dictionary<char, int> duplicateCounts = text
.GroupBy(c => c)
.Where(g => g.Count() > 1)
.ToDictionary(g => g.Key, g => g.Count());
I've shown it as second approach because you should first understand the standard way.
string name = "this is a a program program";
var arr = name.Split(' ').ToArray();
var dup = arr.Where(p => arr.Count(q => q == p) > 1).Select(p => p);
HashSet<string> hash = new HashSet<string>(dup);
string duplicate = string.Join(" ", hash);
You can do this through `LINQ
string name = "this is a a program program";
var d = name.Split(' ').GroupBy(x => x).Select(y => new { word = y.Key, Wordcount = y.Count() }).Where(z=>z.cou > 1).ToList();
Use LINQ to group values:
public static IEnumerable<T> GetDuplicates<T>(this IEnumerable<T> list)
{
return list.GroupBy(item => item).SelectMany(group => group.Skip(1));
}
public static bool HasDuplicates<T>(this IEnumerable<T> list)
{
return list.GetDuplicates().IsNotEmpty();
}
Then you use these extensions like this:
var list = new List<string> { "a", "b", "b", "c" };
var duplicatedValues = list.GetDuplicates();
I have an instance of type List<string[]> I would to convert this to a string with a each string[] on a newline. I'm using the following LINQ query to flatten out the list however I'm not sure how I can add a new line between each string[] without expanding my query into something far more ugly. Is there a way to do it without gutting my query and using String.Join or IEnumberable.Aggregate inside a foreach loop?
results.SelectMany(x => x).Aggregate((c, n) => c + ", " + n)
String.Join(Environment.NewLine, results.Select(a => String.Join(", ", a)));
Complete sample:
var results = new List<string[]> {
new[]{"this", "should", "be", "on"},
new[]{"other", "line"}
};
var result = String.Join(Environment.NewLine,
results.Select(a => String.Join(", ", a)));
Result:
this, should, be, on
other, line
UPDATE Here is aggregation done right - it uses StringBuilder to build single string in memory
results.Aggregate(new StringBuilder(),
(sb, a) => sb.AppendLine(String.Join(",", a)),
sb => sb.ToString());
results.Select(sa => sa.Aggregate((a, b) => a + ", " + b))
.Aggregate((c, d) => c + Enviroment.NewLine + d);
I have a string array of 3000 words. How can I divide the array into groups of ten using LINQ. Each ten items should be stored in one variable. The result should be a new array containing the groups.
Assuming that the words are separated by single space, you can split and re-group like this:
var res = longWord
.Split(' ').
.Select((s, i) => new { Str = s, Index = i })
.GroupBy(p => p.Index / 10)
.Select(g => string.Join(" ", g.Select(v => v.Str)));
I'm looking for the one liner here, starting with:
int [] a = {1, 2, 3};
List<int> l = new List<int>(a);
and ending up with
String s = "1,2,3";
String s = String.Join(",", a.Select(i => i.ToString()).ToArray());
string s = string.Join(",", Array.ConvertAll(a, i => i.ToString()));
or in .NET 4.0 you could try (although I'm not sure it will compile):
string s = string.Join(",", a);
String.Join(",", l);
string.Join(",", l.ConvertAll(i => i.ToString()).ToArray());
This is assuming you are compiling under .NET 3.5 w/ Linq.
int[] array = {1,2,3};
string delimited = string.Join(",", array);
l.Select(i => i.ToString()).Aggregate((s1, s2) => s1 + "," + s2)
Another way of doing it:
string s = a.Aggregate("", (acc, n) => acc == "" ? n.ToString() : acc + "," + n.ToString());
I know you're looking for a one liner, but if you create an extension method, all future usage is a one liner. This is a method I use.
public static string ToDelimitedString<T>(this IEnumerable<T> items, string delimiter)
{
StringBuilder joinedItems = new StringBuilder();
foreach (T item in items)
{
if (joinedItems.Length > 0)
joinedItems.Append(delimiter);
joinedItems.Append(item);
}
return joinedItems.ToString();
}
For your list it becomes: l.ToDelimitedString(",")
I added an overload that always uses comma as the delimiter for convenience.