将数字映射到字母

时间:2011-06-23 12:19:03

标签: c#

我有一个面试问题,问:

  

文本文件包含以下行>

            1: A C D
            4: A B
            5: D F
            7: A E
            9: B C  
     

*每一行都有一个唯一的整数后跟冒号和一个或   更多信件。这些信是   分隔空格(一个或多个)>

                            #2 Write a short program in the language
     您选择的

输出已排序的   列表如

            A: 1 4 7
            B: 4 9
            C: 1 9
            D: 1 5
            E: 7
            F: 5

我不是在找人来解决它,但我总是对这样的问题感到困惑。我想在C#中这样做,并且想知道我应该将每一行存储在一个二维数组中吗?处理这个问题的最佳方法是什么。存储后,我如何用字母而不是数字重新连接每一行?

只是在这里寻找指示。

9 个答案:

答案 0 :(得分:2)

您可以通过为一组数字创建Lookup映射字母来解决问题。您可以使用扩展方法ToLookup创建Lookup


警告:前方的剧透

使用LINQ你可以这样做(打破无效输入):

var text = @"1: A C D
4: A B
5: D F
7: A E
9: B C";

var lookup = text
  .Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
  .Select(
    line => new {
      Number = Int32.Parse(line.Split(':').First()),
      Letters = line.Split(':').Skip(1).First().Split(
        new[] {' '}, StringSplitOptions.RemoveEmptyEntries
      )
    }
  )
  .SelectMany(x => x.Letters, (x, letter) => new { x.Number, Letter = letter })
  .OrderBy(x => x.Letter)
  .ToLookup(x => x.Letter, x => x.Number);

foreach (var item in lookup)
  Console.WriteLine(item.Key + ": " + String.Join(" ", item.ToArray()));

答案 1 :(得分:1)

有助于你解决这个问题的事情

IDictionary<char, IList<int> >

另一个Linq Masturbatory实施(“看马!没有循环!”)

using System;
using System.IO;
using System.Linq;

public static class Program
{
    public static void Main(string[] args)
    {
        File.ReadAllLines("input.txt")
            .Select(line => 
            { 
                var split = line.Split(":".ToCharArray(), 2);
                return new { digit = split[0].Trim().Substring(0,1),
                     chars = split[1]
                        .Split(" \t".ToCharArray())
                        .Select(s=>s.Trim())
                        .Where(s => !String.IsNullOrEmpty(s))
                        .Select(s => s[0])
                    };
            })
            .SelectMany(p => p.chars.Select(ch => new { p.digit, ch }))
            .GroupBy(p => p.ch, p => p.digit)
            .ToList()
            .ForEach(g => Console.WriteLine("{0}: {1}", g.Key, string.Join(" ", g)));
    }
}

当然,您可以将GroupBy替换为ToLookup

答案 2 :(得分:1)

如果您熟悉LINQ,以下代码可以为您提供所需内容:

var result = File.ReadAllLines("inFile").SelectMany(line =>
                {
                    var ar = line.Split(" ".ToCharArray());
                    var num = int.Parse(ar[0].Split(":".ToCharArray())[0]);
                    return ar.Skip(1).Select(s => new Tuple<string, int>(s, num));
                }).GroupBy(t => t.Item1).OrderByDescending(g => g.Count())
                .Select(g => g.Key + ": " + g.Select(t => t.Item2.ToString()).Aggregate( (a,b) => a + " " + b));
            File.WriteAllLines("outFile", result);

答案 3 :(得分:1)

我知道你说你不想要完整答案,但这种事情很有趣。看起来其他人已经提出了类似的解决方案,但这是代表它的另一种方式 - 代码的“一行”(但很多括号!):)

var data = @"1: A C D
4: A B
5: D F
7: A E
9: B C";

Console.WriteLine(
    String.Join(
        Environment.NewLine,
        (from line in data.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
         let lineParts = line.Split(new[] { ':', ' ' }, StringSplitOptions.RemoveEmptyEntries)
         from letter in lineParts.Skip(1)
         select new { Number = lineParts[0], Letter = letter })
        .ToLookup(l => l.Letter, l => l.Number)
        .OrderBy(l => l.Key)
        .Select(l => String.Format("{0}: {1}", l.Key, String.Join(" ", l)))));

哦,我会在制作中编写类似的代码吗?可能不是,但这样的练习很有趣!

答案 4 :(得分:0)

我将使用Dictionary<string,List<int>>我将读取输入,并在键A,C,D,A键A,B等的列表中添加1,因此结果只是一个字母查找。 所以这样,以一种非深奥的方式:

 string inp = @"1: A C D
            4: A B
            5: D F
            7: A E
            9: B C";
            Dictionary<string, List<int>> res = new Dictionary<string, List<int>>();
            StringReader sr = new StringReader(inp);
            string line;
            while (null != (line = sr.ReadLine()))
            {
                if (!string.IsNullOrEmpty(line))
                {
                    string[] tokens = line.Split(": ".ToArray(),StringSplitOptions.RemoveEmptyEntries);
                    int idx = int.Parse(tokens[0]);
                    for (int i = 1; i < tokens.Length; ++i)
                    {
                        if (!res.ContainsKey(tokens[i]))
                            res[tokens[i]] = new List<int>();
                        res[tokens[i]].Add(int.Parse(tokens[0]));
                    }
                }
            }

res将包含letter-&gt;数字列表的结果。

答案 5 :(得分:0)

使用Split(“:”)和Split(“”)进行字符串解析。 然后填写

Dictionary<int, List<string>>

并将其翻译为

Dictionary<string, List<int>>

答案 6 :(得分:0)

您可以将输入存储在IDictionary中,然后将其反转以生成输出。

看看this question

答案 7 :(得分:0)

我看到已经发布了多个相似(循环)和不那么相似(linq)的解决方案但是因为我写了这个,我以为我会把它扔进混合中。

static void Main(string[] args)
{
    var result = new SortedDictionary<char, List<int>>();
    var lines = System.IO.File.ReadAllLines(@"input.txt");
    foreach (var line in lines)
    {
        var split = line.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries);
        var lineNumber = Int32.Parse(split[0].Substring(0,1));
        foreach (var letter in split.Skip(1))
        {
            var key = letter[0];
            if (!result.ContainsKey(key))
            {
                result.Add(key, new List<int> { lineNumber });
            }
            else
            {
                result[key].Add(lineNumber);
            }
        }
    }
    foreach (var item in result)
    {
        Console.WriteLine(String.Format("{0}: {1}", item.Key, String.Join(" ", item.Value)));
    }
    Console.ReadKey();
}

答案 8 :(得分:0)

面试过程的一个重要部分是询问和验证假设。虽然您的描述声明文件的结构为整数后跟字母,但您给出的示例按递增顺序显示整数。如果是这种情况,您可以避免所有LINQ疯狂并实施更有效的解决方案:

var results = new Dictionary<char, List<int>>();

foreach (var line in File.ReadAllLines(@"input.txt"))
{
    var split = line.Split(new []{' '}, StringSplitOptions.RemoveEmptyEntries);
    var num = int.Parse(split[0].TrimEnd(':'));

    for (int i = 1; i < split.Length; i++)
    {
        char letter = split[i][0];
        if (!results.ContainsKey(letter))
            results[letter] = new List<int>();

        results[letter].Add(num);
    }
}