Remove duplicate emails from to , cc and bcc to send grid - c#

I have a lambda expression to remove duplicate emails from to cc and bcc.
lstCCEmailAddress.Remove(lstCCEmailAddress.Where(t => t.Email.Contains(email.Email, StringComparison.OrdinalIgnoreCase)).FirstOrDefault());
but the thing is I want to remove all the duplicate emails just not FirstOrDefault.
which one should I replace FirstOrDefault with
How can I re-write the above query.
Thanks in advance.

To remove duplicates for all those fields (TO,CC,BCC),
first you need to run distinct on "To"
second run distinct on "cc" then remove any emails which does exists from "to".
third run distinct on "bcc" and remove any records which does exists from "to" and "cc" fields
[Fact]
public void TestUniqeEmails()
{
var listToEmail = new List<string> { "a#a.com", "b.com", "b.com" };
var listCCToEmail = new List<string> { "a#a.com", "b.com", "c.com" };
var listBCCToEmail = new List<string> { "a#a.com", "b.com", "c.com", "d.com" };
var uniqueToEmail = listToEmail.Distinct();
var uniqueCCEmail = listCCToEmail
.Where(e => !uniqueToEmail.Any(e.Contains))
.Distinct();
var uniqueBCCEmail = listBCCToEmail
.Where(e => !listToEmail.Any(e.Contains))
.Where(e => !uniqueCCEmail.Any(e.Contains))
.Distinct();
Assert.Equal(2, uniqueToEmail.ToList().Count);
Assert.Single(uniqueCCEmail.ToList());
Assert.Single(uniqueBCCEmail.ToList());
}

You can use the .Distinct() function Of Linq.
static void Main(string[] args)
{
List<string> mail = new List<string>() { "test#gmail", "blub#gmail", "test#gmail" };
var x = mail.Distinct();
foreach (var item in x)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
Result:
test#gmail
blub#gmail
For more information:
https://learn.microsoft.com/de-de/dotnet/api/system.linq.enumerable.distinct?view=net-5.0

You can group by and select group
var DistinctItems = lstCCEmailAddress.GroupBy(x => x. Email).Select(y => y.First());

Related

Extracting only one property in List<Object> to List<String>

public async Task<IEnumerable<String>> GetUsersAsStringBysearch(string userSearch)
{
//This returns List<UserTable>
var item = await riskDBContext.UserTables.Where(e => e.Email.Contains(userSearch)).ToListAsync(); ;
List<string> m_oEnum = new List<string>();
foreach (var user in item)
{
m_oEnum.Add(user.Email);
}
//this is when we fullyindex the table
//var item = await riskDBContext.UserTables.Where(x => EF.Functions.FreeText(x.Email,userSearch)).ToListAsync();
return m_oEnum;
}
var item = await riskDBContext.UserTables.Where(e =>
e.Email.Contains(userSearch)).ToListAsync(); ;
returns List<UserTable>, I want only the email id as an List<string>
Is there a one line statement to achieve, instead of looping the List and adding it to a List<String>
Use .Select(e => e.Email) to create a projection

Combine LINQ and Foreach which in turn creates another list

I have the following piece of code which I am trying to improve:
var ApprovedAllowancesProductIds = from item in ApprovedAllowancesListFiltered select item.ProductId; //(1)
List<Product> productList = new List<Product>();
List<string> partitionProductKeys = new List<string>();
foreach (var item in ApprovedAllowancesProductIds) //(2)
{
string[] partitionKey = new string[] { CountryCD, item.ToString() };
string PartitionKey = partitionKey.ConcatenatedStringWithPipeSeparator();
partitionProductKeys.Add(PartitionKey);
}
var resultProduct = await _tableStorageService.FetchDataByMultiplePartitionKey<Product>(partitionProductKeys, QueryComparisonEnums.Equal);
productList.Add((Product)resultProduct);
For better performance I want to combine the functionality of (2) i.e., the entire foreach loop in (1). I saw some example as: Example1 and Example2 but they don't serve my purpose so please don't mark this as duplicate.
you could combine with Select
var partitionProductKeys = ApprovedAllowancesProductIds
.Select(item =>
{
string[] partitionKey = new string[] { CountryCD, item.ToString() };
return partitionKey.ConcatenatedStringWithPipeSeparator();
})
.ToList();
you could apply the same concept with ApprovedAllowancesListFiltered if you want to merge the fist line as well with this code.
I suggest you remove the outer list completely and loop on the objects instead of the property ProductId of the objects:
List<Product> productList = new List<Product>();
List<string> partitionProductKeys = new List<string>();
foreach (var item in ApprovedAllowancesListFiltered)
{
string[] partitionKey = new string[] { CountryCD, item.ProductId.ToString() };
string PartitionKey = partitionKey.ConcatenatedStringWithPipeSeparator();
partitionProductKeys.Add(PartitionKey);
}
var resultProduct = await _tableStorageService.FetchDataByMultiplePartitionKey<Product>(partitionProductKeys, QueryComparisonEnums.Equal);
productList.Add((Product)resultProduct);
I hope this helps.

How to select data in rows using LINQ?

How can I use LINQ to select all the Company Name and Company ID from all the rows? I need something like this pseudo-code:
var typedQry = from b in allData.AsEnumerable()
where b.GetHeader("xxx") == "08/10/09 to 08/26/09"
select CompanyName, CompanyID, ...
The code below selects only one Company Name. Instead, I want Company Name from all the rows:
var typedQry3 = from b in allData.AsEnumerable()
select new { compname0 = b._rows[0][5]};
The data in _rows are Company Name (e.g., allData[0]._rows[0][5], allData[0]._rows[1][5],....), Company ID, and so forth.
However, Company Name, Company ID, and etc. are not defined in the DataProperty class. Their values are inserted into _rows from data files.
Any help is appreciated. Below is some code to help you understand my question.
List<DataProperty> allData = new List<DataProperty>();
The DataProperty class consists of
private readonly Dictionary<string, string> _headers = new Dictionary<string, string>();
private readonly List<string[]> _rows = new List<string[]>();
and these methods (among others):
public string[] GetDataRow(int rowNumber){return _rows[rowNumber];}
public void AddDataRow(string[] row){_rows.Add(row);}
according to your comment, if you need to the sum for each company you can try this:
var RowList1 = allData.SelectMany(u => u._rows.Select(t => new
{
CompanyName = t[5],
Amount = Convert.ToInt64(t[1]) + Convert.ToInt64(t[2])
}))
.Where(u => u.CompanyName == "XXX")
.OrderBy(u => u.CompanyName)
.ToList();
and if you need to sum of the all companies, you can try this:
var SumAmount = allData.SelectMany(u => u._rows.Select(t => new
{
CompanyName = t[5],
Amount = Convert.ToInt64(t[1]) + Convert.ToInt64(t[2])
}))
.Where(u => u.CompanyName == "XXX")
.DefaultIfEmpty()
.Sum(u => u.Amount);
you can write your own and customized query using these
you can use this to get all company names:
var AllCompanyNames = allData.SelectMany(u => u._rows.Select(t => t[5])).ToList();
and this, to get more property:
var Rows = allData.SelectMany(u =>
u._rows.Select(t => new
{
CompanyName = t[5],
Other1 = t[1],
Other2 = t[2]
}))
.ToList();
and this, if you need to check any condition:
var FilteredRows = allData.SelectMany(u =>
u._rows.Select(t => new
{
CompanyName = t[5],
Other1 = t[1],
Other2 = t[2]
}))
.Where(u => u.CompanyName == "XXX")
.ToList();
At first you can receive rows and then iterate through them.
This example may help you
var rows = (from DataRow dRow in dTable.Rows
select new {col1=dRow["dataColumn1"],col2=dRow["dataColumn2"]});
foreach (var row in distinctRows)
{
var value1=row.col1.ToString();
var value2=row.col2.ToString();
}

Count distinct values of a column in dataGridView using linq in .NET

I need to count and present distinct/unique values in a dataGridView.
I want to present it like this, and this code works just fine with lists.
List<string> aryIDs = new List<string>();
aryIDs.Add("1234");
aryIDs.Add("4321");
aryIDs.Add("3214");
aryIDs.Add("1234");
aryIDs.Add("4321");
aryIDs.Add("1234");
var result= aryIDs.GroupBy(id => id).OrderByDescending(id => id.Count()).Select(g => new { Id = g.Key, Count = g.Count() });
But when I try to use the same approach on a column in dataGridView I get an error saying that groupBy cannot be used on my dataGridView.
DataGridView dataGridView1= new DataGridView();
dataGridView1.Columns.Add("nr", "nr");
string[] row1 = new string[] { "1234" };
string[] row2 = new string[] { "4321" };
string[] row3 = new string[] { "3214" };
string[] row4 = new string[] { "1234" };
string[] row5 = new string[] { "4321" };
string[] row6 = new string[] { "1234" };
object[] rows = new object[] { row1, row2, row3, row4, row5, row6 };
foreach (string[] rowArray in rows)
{
dataGridView1.Rows.Add(rowArray);
}
var result = dataGridView1.GroupBy(id => id).OrderByDescending(id => id.Count()).Select(g => new { Id = g.Key, Count = g.Count() });
So my question is, how do I adapt this linq syntax to work with a column in dataGridView? If possible, i dont want to use lists at all.
This will work for your example:
var result = dataGridView1.Rows.Cast<DataGridViewRow>()
.Where(r => r.Cells[0].Value != null)
.Select (r => r.Cells[0].Value)
.GroupBy(id => id)
.OrderByDescending(id => id.Count())
.Select(g => new { Id = g.Key, Count = g.Count() });
I think this will do it, but I'm not 100% sure. Try it out, if you have any issues let me know...
var distinctRows = (from GridViewRow row in dataGridView1.Rows
select row.Cells[0]
).Distinct().Count();

LINQ: ...Where(x => x.Contains(string that start with "foo"))

Given a collection of the following class:
public class Post
{
...
public IList<string> Tags { get; set; }
}
Is there an easy way to get all Posts that contain a tag starting with "foo" using LINQ?
var posts = new List<Post>
{
new Post { Tags = new[] { "fooTag", "tag" }},
new Post { Tags = new[] { "barTag", "anyTag" }},
new Post { Tags = new[] { "someTag", "fooBarTag" }}
};
var postsWithFooTag = posts.Where(x => [some fancy LINQ query here]);
postsWithFooTag should now contain items 1 and 3 of posts.
Use string's StartsWith
var postsWithFooTag = posts.Where(x => x.Tags.Any(y => y.StartsWith("foo")));
x.Any will check if any element matches some condition. StartsWith checks if the element starts with a certain string.
The above returned:
new Post { Tags = new[] { "fooTag", "tag" }},
new Post { Tags = new[] { "someTag", "fooBarTag" }}
To make it case insensitive use StringComparison.OrdinalIgnoreCase.
var postsWithFooTag = posts.Where(x => x.Tags.Any(y => y.StartsWith("FoO", StringComparison.OrdinalIgnoreCase)));
Returns:
new Post { Tags = new[] { "fooTag", "tag" }},
new Post { Tags = new[] { "someTag", "fooBarTag" }}
while StartsWith("FoO") returns no results.
Try this:
var postsWithFooTag = posts.Where(x => x.Tags.Any(y => y.StartsWith("foo")))
I believe this will work for what you're trying to do.
posts.Where(p => p.Tags.Any(t => t.StartsWith("foo")))
var tag = "foo";
var postsWithFooTag =
posts.Where( p=> p.Tags.Any( t => t.StartsWith(tag)));
Try x => x.Tags.Any(tag => tag.StartsWith("foo"))

Categories

Resources