如何以交替顺序对两个不同对象列表的 XMLArray 项目进行排序?
Ho do I ordering XMLArray Items of two different object list in alternate order?
我有 class 类型,其中有两个不同对象类型的列表。当我尝试序列化 Class 类型时,我按顺序获取列表,但我想按交替顺序获取项目列表。
public class Type
{
private List<Slow> slowField;
private List<Fast> FastField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("SLOW", Order=1)]
public List<Slow> SLOW
{
get
{
return this.slowField;
}
set
{
this.slowField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("FAST", Order=2)]
public List<Fast> FAST
{
get
{
return this.FastField;
}
set
{
this.FastField = value;
}
}
}
当前输出:
<Type>
<SLOW>S1</SLOW>
<SLOW>S2</SLOW>
<SLOW>S3</SLOW>
<FAST>F1</FAST>
<FAST>F2</FAST>
<FAST>F3</FAST>
</Type>
我需要这个输出:
<Type>
<SLOW>S1</SLOW>
<FAST>F1</FAST>
<SLOW>S2</SLOW>
<FAST>F2</FAST>
<SLOW>S3</SLOW>
<FAST>F3</FAST>
</Type>
只是交替输出,迭代的奇数打印第一个列表,如果偶数打印第二个列表。做这样的事情:
for( int i = 1; i < ListLength; i++)
{
if( i%2 == 0)
{
// put here your second list dont forget to put i-1 since we started with 1 in for
print(" The value is even");
}
else
{
//put here your first list
print("the value is odd");
}
}
一种方法是引入第三个集合,它将按所需顺序组合两个现有集合。例如,
假设Fast和Slow的结构如下
public class Fast
{
public int Value{get;set;}
}
public class Slow
{
public int Value{get;set;}
}
您现在可以为这两种类型引入一个基础 Class(或使用 System.Object 作为公共基础)。例如,
public class Base{}
public class Fast:Base
{
public int Value{get;set;}
}
public class Slow:Base
{
public int Value{get;set;}
}
现在您可以在类型 Class 中添加第三个集合,如下所示
[XmlElement("SLOW", Type = typeof(Slow))]
[XmlElement("FAST", Type = typeof(Fast))]
public List<Base> Complete => GetMergedList();
private List<Base> GetMergedList()
{
int minLen = Math.Min(SLOW.Count, FAST.Count);
var list = SLOW.Take(minLen)
.Zip(FAST.Take(minLen), (a, b) => new Base[] { a, b })
.SelectMany(array => array)
.Concat(SLOW.Skip(minLen))
.Concat(FAST.Skip(minLen));
return list.ToList();
}
请注意,代码假设 Fast 和 Slow 集合已经单独排序,但如果没有,则需要添加对它们进行排序的逻辑。
您还需要用 XmlIgnoreAttribute
标记现有属性,以便在序列化期间跳过它们。
[XmlIgnore]
public List<Slow> SLOW
{
....
}
[XmlIgnore]
public List<Fast> SLOW
{
....
}
现在您可以序列化 Type 实例以获得所需的结果。
这是一个使用 IXmlSerialize 的复杂解决方案。我不知道 类 快和慢的细节。所以我只是对 xml 元素的内部文本进行排序
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Schema;
using System.Xml.Linq;
using System.IO;
using System.Text.RegularExpressions;
namespace ConsoleApplication2
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
Type test = new Type()
{
FAST = new List<Fast>() { new Fast() { value = "F1" }, new Fast() { value = "F2" }, new Fast() { value = "F3" } },
SLOW = new List<Slow>() { new Slow() { value = "S1" }, new Slow() { value = "S2" }, new Slow() { value = "S3" } }
};
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
XmlWriter writer = XmlWriter.Create(FILENAME, settings);
XmlSerializer serializer = new XmlSerializer(typeof(Type));
serializer.Serialize(writer, test);
}
}
public class Fast
{
public string value { get; set; }
}
public class Slow
{
public string value { get; set; }
}
public class Type : IXmlSerializable
{
private List<Slow> slowField;
private List<Fast> FastField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("SLOW", Order = 1)]
public List<Slow> SLOW
{
get
{
return this.slowField;
}
set
{
this.slowField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("FAST", Order = 2)]
public List<Fast> FAST
{
get
{
return this.FastField;
}
set
{
this.FastField = value;
}
}
public void WriteXml(XmlWriter writer)
{
string pattern = @"(?'prefix'.*)(?'suffix'\d+)";
XmlSerializer fastSerializer = new XmlSerializer(typeof(Fast));
XmlSerializer slowSerializer = new XmlSerializer(typeof(Slow));
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
settings.ConformanceLevel = ConformanceLevel.Fragment;
settings.Indent = true;
MemoryStream ms = new MemoryStream();
XmlWriter childWriter = XmlWriter.Create(ms,settings);
childWriter.WriteRaw("<Root>");
foreach(Slow slow in slowField)
{
slowSerializer.Serialize(childWriter,slow);
//childWriter.WriteRaw("\n");
}
foreach (Fast fast in FastField)
{
fastSerializer.Serialize(childWriter, fast);
//childWriter.WriteRaw("\n");
}
childWriter.WriteRaw("</Root>");
childWriter.Flush();
ms.Position = 0; ;
string text = Encoding.UTF8.GetString(ms.GetBuffer());
XElement rootElement = XElement.Load(ms);
var orderChildren = rootElement.Elements()
.Select(x => new { match = Regex.Match((string)x, pattern), element = x })
.Select(x => new { prefix = x.match.Groups["prefix"].Value, suffix = x.match.Groups["suffix"].Value, element = x.element })
.OrderBy(x => x.suffix)
.ThenBy(x => x.prefix)
.ToList();
foreach(var orderChild in orderChildren)
{
orderChild.element.WriteTo(writer);
}
}
public void ReadXml(XmlReader reader)
{
XmlSerializer fastSerializer = new XmlSerializer(typeof(Fast));
XmlSerializer slowSerializer = new XmlSerializer(typeof(Slow));
while (!reader.EOF)
{
if (reader.Name == "SLOW")
{
if (slowField == null) slowField = new List<Slow>();
slowField.Add((Slow)slowSerializer.Deserialize(reader));
}
if (reader.Name == "FAST")
{
if (FastField == null) FastField = new List<Fast>();
FastField.Add((Fast)slowSerializer.Deserialize(reader));
}
}
}
public XmlSchema GetSchema()
{
return (null);
}
}
}
我有 class 类型,其中有两个不同对象类型的列表。当我尝试序列化 Class 类型时,我按顺序获取列表,但我想按交替顺序获取项目列表。
public class Type
{
private List<Slow> slowField;
private List<Fast> FastField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("SLOW", Order=1)]
public List<Slow> SLOW
{
get
{
return this.slowField;
}
set
{
this.slowField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("FAST", Order=2)]
public List<Fast> FAST
{
get
{
return this.FastField;
}
set
{
this.FastField = value;
}
}
}
当前输出:
<Type>
<SLOW>S1</SLOW>
<SLOW>S2</SLOW>
<SLOW>S3</SLOW>
<FAST>F1</FAST>
<FAST>F2</FAST>
<FAST>F3</FAST>
</Type>
我需要这个输出:
<Type>
<SLOW>S1</SLOW>
<FAST>F1</FAST>
<SLOW>S2</SLOW>
<FAST>F2</FAST>
<SLOW>S3</SLOW>
<FAST>F3</FAST>
</Type>
只是交替输出,迭代的奇数打印第一个列表,如果偶数打印第二个列表。做这样的事情:
for( int i = 1; i < ListLength; i++)
{
if( i%2 == 0)
{
// put here your second list dont forget to put i-1 since we started with 1 in for
print(" The value is even");
}
else
{
//put here your first list
print("the value is odd");
}
}
一种方法是引入第三个集合,它将按所需顺序组合两个现有集合。例如,
假设Fast和Slow的结构如下
public class Fast
{
public int Value{get;set;}
}
public class Slow
{
public int Value{get;set;}
}
您现在可以为这两种类型引入一个基础 Class(或使用 System.Object 作为公共基础)。例如,
public class Base{}
public class Fast:Base
{
public int Value{get;set;}
}
public class Slow:Base
{
public int Value{get;set;}
}
现在您可以在类型 Class 中添加第三个集合,如下所示
[XmlElement("SLOW", Type = typeof(Slow))]
[XmlElement("FAST", Type = typeof(Fast))]
public List<Base> Complete => GetMergedList();
private List<Base> GetMergedList()
{
int minLen = Math.Min(SLOW.Count, FAST.Count);
var list = SLOW.Take(minLen)
.Zip(FAST.Take(minLen), (a, b) => new Base[] { a, b })
.SelectMany(array => array)
.Concat(SLOW.Skip(minLen))
.Concat(FAST.Skip(minLen));
return list.ToList();
}
请注意,代码假设 Fast 和 Slow 集合已经单独排序,但如果没有,则需要添加对它们进行排序的逻辑。
您还需要用 XmlIgnoreAttribute
标记现有属性,以便在序列化期间跳过它们。
[XmlIgnore]
public List<Slow> SLOW
{
....
}
[XmlIgnore]
public List<Fast> SLOW
{
....
}
现在您可以序列化 Type 实例以获得所需的结果。
这是一个使用 IXmlSerialize 的复杂解决方案。我不知道 类 快和慢的细节。所以我只是对 xml 元素的内部文本进行排序
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Schema;
using System.Xml.Linq;
using System.IO;
using System.Text.RegularExpressions;
namespace ConsoleApplication2
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
Type test = new Type()
{
FAST = new List<Fast>() { new Fast() { value = "F1" }, new Fast() { value = "F2" }, new Fast() { value = "F3" } },
SLOW = new List<Slow>() { new Slow() { value = "S1" }, new Slow() { value = "S2" }, new Slow() { value = "S3" } }
};
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
XmlWriter writer = XmlWriter.Create(FILENAME, settings);
XmlSerializer serializer = new XmlSerializer(typeof(Type));
serializer.Serialize(writer, test);
}
}
public class Fast
{
public string value { get; set; }
}
public class Slow
{
public string value { get; set; }
}
public class Type : IXmlSerializable
{
private List<Slow> slowField;
private List<Fast> FastField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("SLOW", Order = 1)]
public List<Slow> SLOW
{
get
{
return this.slowField;
}
set
{
this.slowField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("FAST", Order = 2)]
public List<Fast> FAST
{
get
{
return this.FastField;
}
set
{
this.FastField = value;
}
}
public void WriteXml(XmlWriter writer)
{
string pattern = @"(?'prefix'.*)(?'suffix'\d+)";
XmlSerializer fastSerializer = new XmlSerializer(typeof(Fast));
XmlSerializer slowSerializer = new XmlSerializer(typeof(Slow));
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
settings.ConformanceLevel = ConformanceLevel.Fragment;
settings.Indent = true;
MemoryStream ms = new MemoryStream();
XmlWriter childWriter = XmlWriter.Create(ms,settings);
childWriter.WriteRaw("<Root>");
foreach(Slow slow in slowField)
{
slowSerializer.Serialize(childWriter,slow);
//childWriter.WriteRaw("\n");
}
foreach (Fast fast in FastField)
{
fastSerializer.Serialize(childWriter, fast);
//childWriter.WriteRaw("\n");
}
childWriter.WriteRaw("</Root>");
childWriter.Flush();
ms.Position = 0; ;
string text = Encoding.UTF8.GetString(ms.GetBuffer());
XElement rootElement = XElement.Load(ms);
var orderChildren = rootElement.Elements()
.Select(x => new { match = Regex.Match((string)x, pattern), element = x })
.Select(x => new { prefix = x.match.Groups["prefix"].Value, suffix = x.match.Groups["suffix"].Value, element = x.element })
.OrderBy(x => x.suffix)
.ThenBy(x => x.prefix)
.ToList();
foreach(var orderChild in orderChildren)
{
orderChild.element.WriteTo(writer);
}
}
public void ReadXml(XmlReader reader)
{
XmlSerializer fastSerializer = new XmlSerializer(typeof(Fast));
XmlSerializer slowSerializer = new XmlSerializer(typeof(Slow));
while (!reader.EOF)
{
if (reader.Name == "SLOW")
{
if (slowField == null) slowField = new List<Slow>();
slowField.Add((Slow)slowSerializer.Deserialize(reader));
}
if (reader.Name == "FAST")
{
if (FastField == null) FastField = new List<Fast>();
FastField.Add((Fast)slowSerializer.Deserialize(reader));
}
}
}
public XmlSchema GetSchema()
{
return (null);
}
}
}