zackmark15
zackmark15

Reputation: 727

Prevent adding duplicate items on ListView

Could someone give me LINQ code to avoid allowing duplicate items when adding new items into ListView?

Here's my current code for adding items from clipboard with regex.

List<string> uri = new List<string>();
string URLPattern = cbRegEx.Text;
string cb = Clipboard.GetText();

uri.Clear();
MatchCollection mc = Regex.Matches(cb, URLPattern, RegexOptions.IgnoreCase);
foreach (Match m in mc)
{
    uri.Add(m.Value);
}

LV_Url.BeginUpdate();
foreach (var Uri in uri)
{
    ListViewItem lv = new ListViewItem();
    lv.Text = (LV_Url.Items.Count + 1).ToString();
    lv.SubItems.Add(GetUrlFileName(Uri));
    lv.SubItems.Add(Uri);
    LV_Url.Items.Add(lv);
    LV_Url.AutoResizeColumn(1, ColumnHeaderAutoResizeStyle.ColumnContent);
}
LV_Url.EndUpdate();

Upvotes: 1

Views: 376

Answers (4)

user10216583
user10216583

Reputation:

To get a distinct string collection from the Clipboard and insert the items into a ListView except the duplicates:

var urls = new List<string>();
//...
//get them from the Clipboard...
//...

//Add the new Urls only:
LV_Url.BeginUpdate();

LV_Url.Items.AddRange(
    urls
    .Distinct()
    .Where(url => LV_Url.Items.Count == 0 
    || LV_Url.FindItemWithText(url, true, 0) == null)
    .Select((url, i) => new ListViewItem(new[]
    {
        (LV_Url.Items.Count + i + 1).ToString(),
        GetUrlFileName(url),
        url
    }
    )).ToArray());

//Optional to fit the contents...
LV_Url.Columns.Cast<ColumnHeader>().ToList().ForEach(c => c.Width = -2);
LV_Url.EndUpdate();

Or add from the Clipboard directly:

LV_Url.BeginUpdate();

LV_Url.Items.AddRange(
    Regex.Matches(Clipboard.GetText(),
    URLPattern, RegexOptions.IgnoreCase | RegexOptions.Multiline)
    .Cast<Match>().Select(m => m.Value) //Or some m.Groups[n].Value...
    .Distinct()
    .Where(url => LV_Url.Items.Count == 0 
    || LV_Url.FindItemWithText(url, true, 0) == null)
    .Select((url, i) => new ListViewItem(new[]
    {
        (LV_Url.Items.Count + i + 1).ToString(),
        GetUrlFileName(url),
        url
    }
    )).ToArray());

LV_Url.Columns.Cast<ColumnHeader>().ToList().ForEach(c => c.Width = -2);
LV_Url.EndUpdate();

Upvotes: 1

zackmark15
zackmark15

Reputation: 727

Finally thanks for all your answer. But this is what I used :) Thanks to @JQSOFT

        LV_Url.BeginUpdate();
        LV_Url.Items.AddRange(Regex.Matches(Clipboard.GetText(), URLPattern, RegexOptions.IgnoreCase | RegexOptions.Multiline)
            .Cast<Match>().Select(m => m.Value)
            .Where(url => LV_Url.Items.Count == 0 || LV_Url.FindItemWithText(url, true, 0) == null)
            .Select((url, i) => new ListViewItem(new[]
            {
                (LV_Url.Items.Count + i + 1).ToString(),
                Util.GetUrlFileName(url),
                url

            })).ToArray());
        LV_Url.EndUpdate();

Upvotes: 1

hsn-mnj
hsn-mnj

Reputation: 1398

Use HashSet<string> instead of using List<string>, it's going to ignore allowing duplicate value in the list.

HashSet<string> list = new HashSet<string>();
list.Add("duplicate");
list.Add("duplicate");
Console.WriteLine(list.Count);//output 1

Upvotes: 4

Farhad Zamani
Farhad Zamani

Reputation: 5861

You can use Distinct() to remove dublicates

MatchCollection mc = Regex.Matches(cb, URLPattern, RegexOptions.IgnoreCase);
foreach (Match m in mc.Distinct())
{
    uri.Add(m.Value);
}

Or

MatchCollection mc = Regex.Matches(cb, URLPattern, RegexOptions.IgnoreCase);
foreach (Match m in mc)
{
    uri.Add(m.Value);
}
uri = uri.Distinct().ToList();

Upvotes: 1

Related Questions