将数字映射到字母
本文关键字:映射 数字 | 更新日期: 2023-09-27 18:00:01
我有一个面试问题问这个:
文本文件有以下行>
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#中做这件事,想知道我应该把每一行都存储在2d数组中吗?处理这个问题的最佳方法是什么。存储后,如何用字母而不是数字重新列出每一行?
只是在这里寻找指针。
您可以通过创建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()));
如果您熟悉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);
我知道你说过你不想要完整的答案,但这种事情很有趣。看起来其他人也提出了类似的解决方案,但这里有另一种表示方式——在"一行"代码中(但有很多括号!):)
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)))));
哦,我会在生产中写这样的代码吗?可能不会,但这样的运动很有趣!
将帮助您解决的事情
IDictionary<char, IList<int> >
另一个Linq手淫的实现("看马!没有循环!")
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)));
}
}
当然,您可以用ToLookup
替换GroupBy
我将使用Dictionary<string,List<int>>
,我将读取输入,并在键a、C、D、a等处向列表中添加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将包含字母->数字列表的结果。
使用拆分(":")和拆分(")进行字符串解析。然后填充
Dictionary<int, List<string>>
并将其翻译成
Dictionary<string, List<int>>
您可以将输入存储在IDictionary中,并对其进行反转以生成输出。
看看这个问题。
我看到已经发布了多个相似(循环)和不太相似(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();
}
面试过程的一个重要部分是询问和验证假设。尽管您的描述指出文件的结构是一个后面跟着字母的整数,但您给出的示例显示了整数的递增顺序。如果是这样的话,您可以避免所有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);
}
}