Как скопировать данные в другой список без linq и без изменения исходного списка - PullRequest
0 голосов
/ 24 октября 2018

В методе GetMaxPrice(), изменения , внесенные в список copy в foreach loop, отражены в originalList!Я использую .Net 2.0 (ToList() и Linq недоступны )

public class DataPair : IComparable<DataPair> 
{
    double _price;
    double _volume;
    public DataPair(double price, double volume)
    {
        _price = price;
        _volume = volume;
    }
    public double Price
    {
        get { return _price; }
        set { _price = value; }
    }
    public double Volume
    {
        get { return _volume; }
        set { _volume = value; }
    }
    public int CompareTo(DataPair that)
    {
        if (this.Volume > that.Volume)
            return -1;
        if (this.Volume == that.Volume)
            return 0;

        return 1;
    }

}
class Program
{
    static void Main(string[] args)
    {
        Random rnd = new Random();
        List<DataPair> origialList = new List<DataPair>();
        for (int indx = 0; indx < 10; indx++ )
            origialList.Add( new DataPair(rnd.Next(1, 100), rnd.Next(1,100)) );

        GetMaxPrice(origialList);
    }
    static double GetMaxPrice(List<DataPair> originalList)
    {
        double max = 0;
        //using a new list and copying using foreach does not change the behaviour
        List<DataPair> copy = new List<DataPair>(originalList.AsReadOnly()); 
        copy.Sort();
        if (copy.Count > 0)
            max = copy[originalList.Count - 1].Price;

        foreach (DataPair item in copy)
            item.Price = item.Volume = 0;

        return max;
    }
}

Ответы [ 3 ]

0 голосов
/ 24 октября 2018

Я бы создал конструктор копирования в классе DataPair, а затем использовал бы его в функции GetMaxPrice.Это создаст новый экземпляр DataPair для каждого элемента в исходном списке, что не повлияет на экземпляры из исходного списка.

public class DataPair : IComparable<DataPair>
{
  double _price;
  double _volume;
  public DataPair(double price, double volume)
  {
    _price = price;
    _volume = volume;
  }
  public DataPair(DataPair dataPair)
  {
    Price = dataPair.Price;
    Volume = dataPair.Volume;
  }
  public double Price
  {
    get { return _price; }
    set { _price = value; }
  }
  public double Volume
  {
    get { return _volume; }
    set { _volume = value; }
  }
  public int CompareTo(DataPair that)
  {
    if (this.Volume > that.Volume)
      return -1;
    if (this.Volume == that.Volume)
      return 0;

    return 1;
  }

}
class Program
{
  static void Main(string[] args)
  {
    Random rnd = new Random();
    List<DataPair> origialList = new List<DataPair>();
    for (int indx = 0; indx < 10; indx++)
      origialList.Add(new DataPair(rnd.Next(1, 100), rnd.Next(1, 100)));

    GetMaxPrice(origialList);
  }
  static double GetMaxPrice(List<DataPair> originalList)
  {
    double max = 0;
    //using a new list and copying using foreach does not change the behaviour
    List<DataPair> copy = new List<DataPair>();
    foreach (var dataPair in originalList)
    {
      copy.Add(new DataPair(dataPair));
    }
    copy.Sort();
    if (copy.Count > 0)
      max = copy[originalList.Count - 1].Price;

    foreach (DataPair item in copy)
      item.Price = item.Volume = 0;

    return max;
  }
}
0 голосов
/ 24 октября 2018

Вы можете использовать интерфейс Iclonable. Ваш класс должен реализовать этот интерфейс, а внутри метода клонирования использовать метод memeberwise clone.

using System;
using System.Collections.Generic;

using System.Text;

namespace StackOverfloeProblem
{
    class Program
    {
        static void Main(string[] args)
        {
            Random rnd = new Random();
            List<DataPair> origialList = new List<DataPair>();
            for (int indx = 0; indx < 10; indx++)
                origialList.Add(new DataPair(rnd.Next(1, 100), rnd.Next(1, 100)));

            GetMaxPrice(origialList);
        }
        static double GetMaxPrice(List<DataPair> originalList)
        {
            double max = 0;
            //using a new list and copying using foreach does not change the behaviour
            List<DataPair> copy= new List<DataPair>();
            foreach (var item in originalList)
            {
                DataPair a = (DataPair)item.Clone();
               copy.Add(a);
            }
            //List<DataPair> copy = originalList.Select(elt => elt.Clone()).ToList();

            copy.Sort();
            if (copy.Count > 0)
                max = copy[originalList.Count - 1].Price;

            foreach (DataPair item in copy)
                item.Price = item.Volume = 0;

            return max;
        }
    }
}

public class DataPair : IComparable<DataPair>,ICloneable
{
    double _price;
    double _volume;
    public DataPair(double price, double volume)
    {
        _price = price;
        _volume = volume;
    }
    public double Price
    {
        get { return _price; }
        set { _price = value; }
    }
    public double Volume
    {
        get { return _volume; }
        set { _volume = value; }
    }
    public int CompareTo(DataPair that)
    {
        if (this.Volume > that.Volume)
            return -1;
        if (this.Volume == that.Volume)
            return 0;

        return 1;
    }


    public object Clone()
    {
        return this.MemberwiseClone();  
    }
}
0 голосов
/ 24 октября 2018

Вы должны сделать глубокое копирование (т.е. клонировать каждый элемент в исходном списке):

// Not shallow copy (copy shares items with originalList)
// List<DataPair> copy = new List<DataPair>(originalList.AsReadOnly()); 

// But deep copy:
List<DataPair> copy = new List<DataPair>();

// copy has its own items (new DataPair...)
foreach (var item in originalList)
  copy.Add(new DataPair(item.Price, item.Volume)); 

Другая возможность состоит в том, чтобы превратить class в struct (так как DataPair содержит 2 double поле только, это хороший кандидат для struct):

// Note "struct" instead of "class"
public struct DataPair : IComparable<DataPair> {
  ...
}

Теперь DataPair будет передано значение (не ссылка ) и

List<DataPair> copy = new List<DataPair>(originalList.AsReadOnly()); 

будут отображаться в виде глубокой копии.

...