我有一个字符串,其中包含所有可供分配的分区字母。
我想从此字符串中删除已经使用的每个字符(或驱动器号)。
我尝试这样做:
string allletters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
DriveInfo[] d = DriveInfo.GetDrives();
string notusedletters = string.Empty;
foreach (DriveInfo drive in AllDrives)
{
string driveLetterOnly = (drive.Name).Replace(@":\", ""); // remove ":\" characters from the drive letter
notusedletters = allletters.Replace(driveLetterOnly, ""); // remove driveLetterOnly from the allletters string.
}
但是notusedletters字符串始终返回所有字母的初始值(ABCDEFGHIJKLMNOPQRSTUVWXYZ)。
此代码有什么问题?
答案 0 :(得分:2)
当您在Replace
上调用allletters
时,将创建一个新字符串。 Replace
不修改存在的字符串。
为了使代码正常工作,您应该在每次迭代中重新分配allletters
:
allletters = allletters.Replace(....)
或仅使用此单行linq查询:
string allletters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string notusedletters = new string(
allletters.Except(
DriveInfo.GetDrives().Select(d => d.Name[0])
).ToArray());
应注意,除不保证保留订单外,
我检查了this个答案,并说Except
保持顺序。为了确保我已经反编译System.Core
请在我的评论中查看Except
的实现:
public static IEnumerable<TSource> Except<TSource>(
this IEnumerable<TSource> first,
IEnumerable<TSource> second)
{
// I removed a null checks
return Enumerable.ExceptIterator<TSource>(first, second,
(IEqualityComparer<TSource>) null);
}
private static IEnumerable<TSource> ExceptIterator<TSource>(
IEnumerable<TSource> first,
IEnumerable<TSource> second,
IEqualityComparer<TSource> comparer)
{
Set<TSource> set = new Set<TSource>(comparer);
foreach (TSource source in second)
set.Add(source);
foreach (TSource source in first)
{
if (set.Add(source))
yield return source; // elements will be yielded in same order
// as they appear in first sequence
}
}
但是要100%确保以后的行为不会改变,您可以使用OrderBy
,如@ckuri在注释中建议的那样:
string notusedletters = new string(
allletters.Except(
DriveInfo.GetDrives().Select(d => d.Name[0])
)
.OrderBy(c => c) // explicit ordering
.ToArray()
);
答案 1 :(得分:1)
在使用notusedletters
时,请勿使用replace
或仅保留相同的字符串。
string allletters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
DriveInfo[] d = DriveInfo.GetDrives();
foreach (DriveInfo drive in d)
{
string driveLetterOnly = (drive.Name).Replace(@":\", ""); // remove ":\" characters from the drive letter
allletters = allletters.Replace(driveLetterOnly, ""); // remove driveLetterOnly from the allletters string.
}
Console.WriteLine(allletters);