Как получить появление первых символов в тексте с сохранением их оригинального порядка? - PullRequest
1 голос
/ 15 марта 2011

Я пытаюсь получить вхождение первого символа в тексте, сохраняя их первоначальный порядок.Я пытаюсь использовать LINQ, но я очень новичок в этом, поэтому что-то не так, и у меня плохой результат.

Например, я пишу: "languages", поэтому результат будет l-0, a-1, n-2, g-3, u-4, e-7, s-8 (цифра означает индекс появления).Но мой код дает: l-0, a-1, n-2, g-3, u-4, e- 5 , s- 6 .

Таким образом, индекс номер 0,1,2,3,4,5 независимо от того, что.Это мой код:

char[] result = text.ToLower()
    .Where(char.IsLetter)
    .GroupBy(x => x)
    .Select(g => g.Key).ToArray();

for (int i = 0; i < result.Length; i++)
{
    listView1.Items.Add(result[i].ToString());
    listView1.Items[i].SubItems.Add(i.ToString());
}

Ответы [ 4 ]

3 голосов
/ 15 марта 2011

Используя LINQ, я полагаю, вы пытаетесь выполнить следующее:

string input = "languages";
var query = input.Select((c, i) => new { Char = c, Index = i })
                 .Where(o => Char.IsLetter(o.Char))
                 .GroupBy(o => o.Char)
                 .Select(g => g.First());

foreach (var item in query)
{
    Console.WriteLine("{0}: {1}", item.Char, item.Index);
}

Вы можете использовать перегруженный метод Select, чтобы получить индекс каждого символа. После захвата оригинальных индексов вы можете в дальнейшем манипулировать результатами. Теперь вы можете фильтровать только символы, группировать их по символам и, наконец, взять элемент First() из каждой группы.

2 голосов
/ 15 марта 2011

Я бы использовал Regex:

using System.Text.RegularExpressions;

var q = from ch in text.Distinct()
        select Regex.Match(text, ch.ToString());
foreach (var item in q)
{
    Console.WriteLine("{0}-{1}", item.Value, item.Index);
}

И альтернатива без регулярных выражений:

var q = from ch in text.Distinct()
        select new { Value = ch, Index = text.IndexOf(ch) };
1 голос
/ 15 марта 2011

Вы можете попробовать это:

string text="languages";
var ints = Enumerable.Range(0,text.Length); 

var firstOccurrences = 
   from couple in text.Zip(ints, (a,b) => new{character=a, index=b})
   where char.IsLetter(couple.character)
   group couple by couple.character into cn
   select new {ch=cn.Key, minindex=cn.Min(c => c.index)};

   foreach(var f in firstOccurrences)
    {
        Console.WriteLine("char:{0} - first occurs: {1}",f.ch,f.minindex);
    }
1 голос
/ 15 марта 2011

Есть ли какая-то конкретная причина, по которой вы хотели использовать LINQ здесь?

Вы не сохраняете позицию первого вхождения в запросе LINQ. То, что вы получаете, это просто список всех персонажей.

Цикл по символам в строке и использование Dictionary<char,int> для сохранения позиции первого вхождения позволят выполнить вашу задачу.

 public static Dictionary<char, int> FirstOccurence(string str)
    {
        char[] strArr = str.ToCharArray();
        Dictionary<char, int> firstOccur = new Dictionary<char, int>();
        for (int i = 0; i < strArr.Length; i++)
        {
            if (!firstOccur.ContainsKey(strArr[i]))
            {
                firstOccur[strArr[i]] = i;
            }
        }
        return firstOccur;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...