如何以交替顺序对两个不同对象列表的 XML 数组项进行排序?

Posted

技术标签:

【中文标题】如何以交替顺序对两个不同对象列表的 XML 数组项进行排序?【英文标题】:Ho do I ordering XMLArray Items of two different object list in alternate order? 【发布时间】:2021-10-31 16:39:35 【问题描述】:

我有类 Type,它有两个不同对象类型的列表。当我尝试序列化类类型时,我按顺序获取列表,但我想以交替顺序获取项目列表。

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>

【问题讨论】:

【参考方案1】:

一种方法是引入第三个 Collection,它将按所需顺序组合两个现有集合。例如,

假设Fast和Slow的结构如下

public class Fast

    public int Valueget;set;


public class Slow

    public int Valueget;set;

您现在可以为这两种类型引入一个基类(或使用 System.Object 作为公共基础)。例如,

public class Base

public class Fast:Base

    public int Valueget;set;


public class Slow:Base

    public int Valueget;set;

现在您可以在您的类型类中添加第三个集合,如下所示

[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 实例以获得所需的结果。

Demo Code

【讨论】:

【参考方案2】:

只需交替输出,如果迭代是奇数,则打印第一个列表,如果偶数打印第二个。做这样的事情:

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");


【讨论】:

但是我是直接序列化Type类。 XMLSerializer 正在打印数据【参考方案3】:

这是一个使用 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);
        
    

【讨论】:

以上是关于如何以交替顺序对两个不同对象列表的 XML 数组项进行排序?的主要内容,如果未能解决你的问题,请参考以下文章

如何对彼此相关的两个数组进行排序?

如何映射两个数组并将匹配项作为按钮返回?

C#根据多个(26 + 3)类别以特定顺序对对象列表进行排序(LINQ,if else,switch case)[关闭]

如何根据另一个数组的顺序对对象数组进行排序?

如何将可迭代拆分为两个具有交替元素的列表

如何比较两个对象数组以删除重复项?