这是我的问题
我有以下数组(例如)
string[] arr = new[] { "s_0001", "s_0002", "s_0003", "sa_0004", "sa_0005", "sab_0006", "sab_0007" };
我想做一些给出以下输出的事情
s_0001
sa_0004
sab_0006
我已经尝试了一切,但没有运气!这将是一个长期项目的第一步,我们将不胜感激任何帮助。
[edit]我不知道字母什么时候会改变,但我知道总会有一个下划线来分隔字母和数字。我需要以某种方式提取这些字母,然后删除重复的字母
[编辑]更具体地说..我想在下划线之前有每个字符串的唯一条目,我不关心的数字
[编辑] 好了 friend 们!你真的很活跃,我给你。我没想到我会这么快得到答案。但看起来(因为我在过去 8 个小时里一直在研究这个问题)我问了错误的问题
这是我的代码
//Loop through the XML files in the Directory and get
//the objectName and GUID of each file
string[] arr_xmlFiles = Directory.GetFiles(Dir, "*.xml"); //Array with all XML Files in the Directory
foreach (string xmlFile in arr_xmlFiles)
{
try
{
//Get the XMLs Name
XDocument xmlF = XDocument.Load(xmlFile);
string objectName = xmlF.Root.Name.ToString();
//Get the XMLs GUID
XElement oDcElement = xmlF.Root.FirstNode as XElement;
Guid oGuid = new Guid(oDcElement.Attribute("DataclassId").Value);
//Prints out the results
Console.WriteLine(" " + objectName + " " + oGuid);
}
catch (XmlException) { }
}
我所做的基本上如下 我获取目录中的所有 XML 文件(它们包含 ObjectName 及其 GUID)
即
CM_Commands [0ee2ab91-4971-4fd3-9752-cf47c8ba4a01].xml
CM_Commands [1f627f72-ca7b-4b07-8f93-c5750612c209].xml
抱歉,中断符号是“[”而不是“_”,但这并不重要。
现在我将所有这些 XML 保存在一个数组中,然后我想从这些 XML 中提取每个 XML 的 ObjectName 和 GUID
完成此操作后,我只想对包含相同 objectName 的每个 XML 之一进行一些修改
就这些了
最佳答案
编辑#3:详细注释添加到下面的代码片段中(请参阅编辑2下的更新代码)。另请注意,如果您想从方法返回这些属性,您需要使用这些属性设置一个新类,例如:
public class MyClass
{
public string ObjectName { get; set; }
public string Guid { get; set; }
public string FileName { get; set; }
}
有了可用的类,select 语句将从 select new { ... }
更改至:
/* start of query unchanged ... */
select new MyClass
{
ObjectName = split[0],
Guid = split[1],
FileName = f.FullName
};
包含所有这些代码的方法的返回类型将为 IEnumerable<MyClass>
。您可以轻松地将其更改为 List<MyClass>
通过使用return results.ToList();
.
编辑#2:要从文件名中提取objectName和Guid,您不需要执行所有繁琐的XML工作从内部详细信息中获取信息。
假设您的objectName
和Guid
总是用空格分隔,您可以使用以下代码。否则可能需要更多的解析(或者可选的正则表达式)。
string path = @"C:\Foo\Bar"; // your path goes here
var dirInfo = new DirectoryInfo(path);
// DirectoryInfo.GetFiles() returns an array of FileInfo[]
// FileInfo's Name property gives us the file's name without the full path
// LINQ let statement stores the split result, splitting the filename on spaces
// and dots to get the objectName, and Guid separated from the file extension.
// The "select new" projects the results into an anonymous type with the specified
// properties and respectively assigned values. I stored the fullpath just in case.
var query = from f in dirInfo.GetFiles("*.xml")
let split = f.Name.Split(new[] { ' ', '.' })
select new
{
ObjectName = split[0],
Guid = split[1],
FileName = f.FullName
};
// Now that the above query has neatly separated the ObjectName, we use LINQ
// to group by ObjectName (the group key). Multiple files may exist under the same
// key so we then select the First item from each group.
var results = query.GroupBy(o => o.ObjectName)
.Select(g => g.First());
// Iterate over the results using the projected property names.
foreach (var item in results)
{
Console.WriteLine(item.FileName);
Console.WriteLine("ObjectName: {0} -- Guid {1}", item.ObjectName, item.Guid);
}
这适合您的示例数据,但是如果您预计文件名带有 .
上面的字符将会被破坏。为了解决这种情况的变化:
Split
至:let split = f.Name.Split(' ')
- 指南:
Guid = split[1].Substring(0, split[1].LastIndexOf('.')),
既然您知道总会有一个下划线,您可以尝试这种方法:
string[] arr = {"s_0001", "s_0002", "s_0003", "sa_0004", "sa_0005", "sab_0006", "sab_0007"};
var query = arr.GroupBy(s => s.Substring(0, s.IndexOf('_')))
.Select(g => g.First());
foreach (string s in query)
Console.WriteLine(s); // s_0001, sa_0004, sab_0006
这将获取每组的第一个项目,因此除非您的项目已预先排序,否则您可能需要输入 OrderBy
在 Select
:.Select(g => g.OrderBy(s => s).First());
编辑:为了响应您的编辑,要获取下划线之前的不同字母(即 s、sa、sab),您可以使用 Enumerable.Distinct方法如下:
var query = arr.Select(s => s.Substring(0, s.IndexOf('_')))
.Distinct(); // s, sa, sab
这会给你一个 IEnumerable<string>
您可以使用 foreach
进行迭代如前所示。
关于c# - 从c#中的数组中提取半相似项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3548360/