Reputation: 5745
Is there anyway to write turn this for each loop into Linq expression:
private List<string> datasetItemset;
Dictionary<string, int> itemsetScanning = new Dictionary<string, int>();
List<string> itemList = new List<string>();
foreach (string transaction in this.datasetItemset)
{
string[] items = transaction.Split(new char[] { ' ' });
foreach (string item in items)
if (!itemList.Contains(item))
{
itemList.Add(item);
itemsetScanning.Add(item, 0);
}
}
My next question is that , does using linq expressions instead of foreach loop speed up the performance of the program, I'm kind of new to this linq.
Update: Using too many foreach loop is slowing down my program.
Upvotes: 1
Views: 836
Reputation: 564323
does using linq expressions instead of foreach loop speed up the performance of the program, I'm kind of new to this linq.
No. Internally, LINQ will still typically perform the same number of iterations, so in general, it won't speed things up. Written properly, LINQ will perform very similarly to the looping.
It is very useful to make the intent more clear, which in turn can sometimes make it simpler to optimize and short curcuit. That being said, those same optimizations can be done on loops just as easily.
Is there anyway to write turn this for each loop into Linq expression:
Yes. This could be done via:
foreach(var item in this.datasetItemset
.SelectMany(transaction => transaction.Split(' '))
.Distinct())
{
itemList.Add(item);
itemsetScanning.Add(item, 0);
}
Note that the inner body/loop is left as a foreach
loop, on purpose, in this case, as it's performing side effects.
Given that it appears you're building list and a set, you could use:
var itemList = this.datasetItemset.SelectMany(transaction => transaction.Split(' ')).ToList();
var uniqueSet = new HashSet<string>(itemList); // Build the set from the list
This would provide you a set of unique values (as a HashSet<string>
) as well as the list of values. If you just need a unique list of values, you can use Distinct
to build it directly:
var uniqueItemList = this.datasetItemset
.SelectMany(transaction => transaction.Split(' '))
.Distinct()
.ToList();
If you need the dictionary, then it's merely taking these results:
var itemsetScanning = uniqueItemList.ToDictionary(i => i, i => 0);
Upvotes: 6
Reputation: 203802
Here's how I would write out that code:
var itemList = datasetItemset.SelectMany(transaction => transaction.Split(' '))
.Distinct()
.ToList();
var itemsetScanning = itemList.ToDictionary(transaction => transaction,
transaction => 0);
This is the more idiomatic LINQ way of addressing the problem.
The nested foreach generally maps to a SelectMany
call, and rather than checking if the item already exists you can use Distinct
, which not only semantically represents what you're trying to do, but will be noticeably more efficient (as you're avoiding repeated linear searches through a list; you could use a HashSet
to more efficiently search in a non-LINQ solution if you wanted). Rather than adding the items to collections, you can instead convert each sequence directly into a collection using ToList
and ToDictionary
, to avoid explicitly using a foreach
.
Upvotes: 1
Reputation: 144126
List<string> itemList = this.datasetItemset
.SelectMany(item => item.Split(' '))
.Distinct()
.ToList();
var itemsetScanning = itemList.ToDictionary(e => e, _ => 0);
Regarding performance, Linq will be slower than a carefully-crafted specific solution, but it is usually quick enough. If performance is an issue for you, you should probably avoid it (after profiling).
Upvotes: 1
Reputation: 125610
You can easily do the same using LINQ:
var itemList = this.datasetItems
.SelectMany(x => x.split(' '))
.Distinct()
.ToList();
var itemssetScanning = itemList.ToDictionary(x => x, x => 0);
However, there still are foreach
loops hidden inside SelectMany
, Distinct
, ToList
and ToDictionary
methods. There is no magic here! Additional delegates calls makes it slower then custom loops.
Upvotes: 0
Reputation: 25370
here is ugly linq
foreach (var item in this.datasetItemset
.Select(transaction => transaction.Split(new char[] { ' ' }))
.SelectMany(items => items
.Where(item => !itemList.Contains(item))))
{
itemList.Add(item);
itemsetScanning.Add(item, 0);
}
Upvotes: 1