Удалить дублирующиеся элементы из списка <String> - PullRequest
2 голосов
/ 01 марта 2012

Я хотел бы удалить дубликаты элементов из списка. Некоторые элементы списка выглядят так:

Book  23
Book  22
Book  19
Notebook 22
Notebook 19
Pen 23
Pen 22
Pen 19

Чтобы избавиться от повторяющихся элементов, я сделал это:

List<String> nodup = dup.Distinct().ToList();

Я бы хотел оставить в списке только

Book 23
Notebook 22
Pen 23

Как я могу это сделать?

Ответы [ 5 ]

4 голосов
/ 01 марта 2012

вы можете сделать что-то вроде

string firstElement = dup.Distinct().ToList().First();

и добавить его в другой список, если хотите.

3 голосов
/ 01 марта 2012

Не на 100% ясно, что вы хотите здесь - однако ...

Если вы хотите сохранить «самый большой» номер в списке, вы можете сделать:

List<string> noDup = dup.Select(s => s.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries)
        .Select(p => new { Name=p[0], Val=int.Parse(p[1]) })
        .GroupBy(p => p.Name)
        .Select(g => string.Join(" ", g.Key, g.Max().ToString()))
        .ToList();

Это преобразует List<string>, анализируя числовую часть в число, беря максимум на элемент и создавая строку вывода, как вы указали.

2 голосов
/ 01 марта 2012

Вы можете использовать LINQ в сочетании с некоторыми String операциями, чтобы сгруппировать всех ваших itemy по имени и MAX(Number):

var q = from str in list
        let Parts = str.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
        let item = Parts[ 0 ]
        let num = int.Parse(Parts[ 1 ])
        group new  { Name = item, Number = num } by item into Grp
        select new {
            Name  = Grp.Key,
            Value = Grp.Max(i => i.Number).ToString()
        };

var highestGroups = q.Select(g => 
    String.Format("{0} {1}", g.Name, g.Value)).ToList();

(То же, что и подход Рида, но в синтаксисе запроса, который лучшена мой взгляд)

Редактировать : я не могу воспроизвести ваш комментарий о том, что он не работает, вот пример данных:

List<String> list = new List<String>();
list.Add("Book  23");
list.Add("Book  22");
list.Add("Book 19");
list.Add("Notebook  23");
list.Add("Notebook  22");
list.Add("Notebook  19");
list.Add("Pen  23");
list.Add("Pen  22");
list.Add("Pen  19");
list.Add("sheet 3");

var q = from str in list
        let Parts = str.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
        let item = Parts[ 0 ]
        let num = int.Parse(Parts[ 1 ])
        group new  { Name = item, Number = num } by item into Grp
        select new {
            Name  = Grp.Key,
            Value = Grp.Max(i => i.Number).ToString()
        };

var highestGroups = q.Select(g => String.Format("{0} {1}", g.Name, g.Value));
MessageBox.Show(String.Join(Environment.NewLine, highestGroups));

Результат:

Book 23
Notebook 23
Pen 23
sheet 3
1 голос
/ 01 марта 2012

Вы можете добавить пользовательский компаратор в качестве параметра, как вы можете видеть в примере на MSDN .

В этом примере я предположил, что Foo - это класс с двумя членами.

class Program
{
    static void Main(string[] args)
    {
        var list = new List<Foo>()
        {
            new Foo("Book", 23),
            new Foo("Book", 22),
            new Foo("Book", 19)
        };

        foreach(var element in list.Distinct(new Comparer()))
        {
            Console.WriteLine(element.Type + " " + element.Value);
        }
    }
}

public class Foo
{
    public Foo(string type, int value)
    {
        this.Type = type;
        this.Value = value;
    }

    public string Type { get; private set; }

    public int Value { get; private set; }
}

public class Comparer : IEqualityComparer<Foo>
{
    public bool Equals(Foo x, Foo y)
    {
        if(x == null || y == null)
            return x == y;
        else
            return x.Type == y.Type;
    }

    public int GetHashCode(Foo obj)
    {
        return obj.Type.GetHashCode();
    }
}

Это работает для IList, предполагая, что мы хотим первый элемент каждого , а не тот, который имеет наибольшее число. Будьте осторожны с разными типами коллекций (например, ICollection или IEnumerable), так как они не гарантируют вам какой-либо заказ. Поэтому любой из Foo может остаться после Distinct.

Вы также можете переопределить Equals и GetHashCode из Foo вместо использования пользовательского IEqualityComparer. Тем не менее, я бы на самом деле не рекомендовал бы это для локального отличного. Потребители вашего класса могут не признать, что два экземпляра с одинаковым значением для Type всегда равны, независимо от их Value.

0 голосов
/ 01 марта 2012

немного старомодно, но оно должно работать, Если я правильно понимаю

    Dictionary<string,int> dict=new Dictionary<string,int>();

    //Split accepts 1 character ,assume each line containes key value pair seperated with spaces and not containing whitespaces
    input=input.Replace("\r\n","\n");
    string[] lines=input.Split('\n');

    //break to categories and find largest number at each 
    foreach(line in lines)
    {
        string parts[]=line.Split(' ');
        string key=parts[0].Trim();
        int value=Convert.ToInt32(parts[1].Trim());

        if (dict.ContainsKey(key))
        {
            dict.Add(key, value);
        }
        else
        {
            if (dict[key]<value)
            {
                    dict[key]=value;
            }
        }

    }


    //do somethig with dict 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...