将列表拆分为+;ve&-使用c#

将列表拆分为+;ve&-使用c#,c#,linq,list,sorting,C#,Linq,List,Sorting,我有一个+ve和-ve值列表,我需要: 分类 将它们转换为int,我将它们乘以100:) 将它们分成两个列表 去掉公共值,它们应该是+ve和-ve对 e、 g input=1.00,2.92,-2.92,3.00,7.56,-7.56,8.00,-100.93,-40.56…… 最终目标: listA = 1, 3, 8 listB = -4056, -10093 listA=1,3,8 listB=-4056,-10093 我正在寻找改进我下面代码的建议,速度和准确性都很重要 var re

我有一个+ve和-ve值列表,我需要:

  • 分类
  • 将它们转换为int,我将它们乘以100:)
  • 将它们分成两个列表
  • 去掉公共值,它们应该是+ve和-ve对
e、 g

input=1.00,2.92,-2.92,3.00,7.56,-7.56,8.00,-100.93,-40.56……

最终目标:

listA = 1, 3, 8 listB = -4056, -10093 listA=1,3,8 listB=-4056,-10093 我正在寻找改进我下面代码的建议,速度和准确性都很重要

var results = new List<decimal>(input.Select(x => x*100 ));
results.Sort();
var listA = results.FindAll(x => ((decimal)x > 0));
var listB = results.FindAll(x => ((decimal)x < 0));
decimal[] FromA_NotIn_B = listA.Except(listB.Select(X => (X = X * -1))).ToArray();
decimal[] FromB_NotIn_A = listB.Except(listA.Select(X => (X = X * -1))).ToArray();
var results=新列表(input.Select(x=>x*100));
results.Sort();
var listA=results.FindAll(x=>((十进制)x>0));
var listB=results.FindAll(x=>((十进制)x<0));
十进制[]from a_NotIn_B=listA.Except(listB.Select(X=>(X=X*-1)).ToArray();
十进制[]from b_NotIn_A=listB.Except(listA.Select(X=>(X=X*-1)).ToArray();

您的代码在精度方面是正确的(十进制在反转其符号时不会失去精度)。它的速度肯定可以提高20倍,通过编写循环和进行手动完全外部合并连接。然而,我只建议在性能非常关键的情况下使用这种方法,因为这将使代码大小增加5倍

编辑:合并联接意味着并排获取两个已排序的列表,并以可以找到相等元素的方式沿着这两个列表移动,即使两个数组中都有多余的元素。这是合并排序中合并步骤的扩展。完全外部表示它在数据库中的含义:保留仅在其中一个数组中的值

唯一的要求,排序列表,是给定的,因为您对结果列表进行排序

您的代码的工作方式如下:

var results = new List<decimal>(input.Select(x => x*100 ));
results.Sort();
var listA = new List<decimal>();
var listB = new List<decimal>();

//now to the merge-join and fill listA and B
var results=新列表(input.Select(x=>x*100));
results.Sort();
var listA=新列表();
var listB=新列表();
//现在到合并连接并填充列表A和B
合并连接的实现将很复杂,但为了让您开始,这里有一个基于迭代器的版本,我在我的项目中使用它来连接两个巨大的文件,我无法将它们加载到内存中,但它们是经过排序的

    public static IEnumerable<TResult> MergeJoin_OneToOne<TLeft, TRight, TResult>(
        IEnumerable<TLeft> leftCollection,
        IEnumerable<TRight> rightCollection,
        Func<TLeft, TRight, int> comparison,
        Func<TLeft, TResult> onlyLeftSelector,
        Func<TRight, TResult> onlyRightSelector,
        Func<TLeft, TRight, TResult> bothSelector)
    {
        return MergeJoin_OneToOne_Impl(leftCollection, rightCollection, comparison, onlyLeftSelector, onlyRightSelector, bothSelector);
    }

    static IEnumerable<TResult> MergeJoin_OneToOne_Impl<TLeft, TRight, TResult>(
        IEnumerable<TLeft> leftCollection,
        IEnumerable<TRight> rightCollection,
        Func<TLeft, TRight, int> comparison,
        Func<TLeft, TResult> onlyLeftSelector,
        Func<TRight, TResult> onlyRightSelector,
        Func<TLeft, TRight, TResult> bothSelector)
    {
        if (leftCollection == null) throw new ArgumentNullException("leftCollection");
        if (rightCollection == null) throw new ArgumentNullException("rightCollection");
        if (comparison == null) throw new ArgumentNullException("comparison");
        if (onlyLeftSelector == null) throw new ArgumentNullException("onlyLeftSelector");
        if (onlyRightSelector == null) throw new ArgumentNullException("onlyRightSelector");
        if (bothSelector == null) throw new ArgumentNullException("bothSelector");

        using (var leftEnum = leftCollection.GetEnumerator())
        using (var rightEnum = rightCollection.GetEnumerator())
        {
            if (!leftEnum.MoveNext())
            {
                while (rightEnum.MoveNext()) yield return onlyRightSelector(rightEnum.Current);
                yield break;
            }

            if (!rightEnum.MoveNext())
            {
                do
                {
                    yield return onlyLeftSelector(leftEnum.Current);
                } while (leftEnum.MoveNext());
                yield break;
            }

            while (true)
            {
                int cmp = comparison(leftEnum.Current, rightEnum.Current);
                if (cmp == 0)
                {
                    yield return bothSelector(leftEnum.Current, rightEnum.Current);

                    if (!leftEnum.MoveNext())
                    {
                        while (rightEnum.MoveNext())
                        {
                            yield return onlyRightSelector(rightEnum.Current);
                        }
                        yield break;
                    }
                    if (!rightEnum.MoveNext())
                    {
                        do
                        {
                            yield return onlyLeftSelector(leftEnum.Current);
                        } while (leftEnum.MoveNext());
                        yield break;
                    }
                }
                else if (cmp < 0)
                {
                    yield return onlyLeftSelector(leftEnum.Current);

                    if (!leftEnum.MoveNext())
                    {
                        do
                        {
                            yield return onlyRightSelector(rightEnum.Current);
                        } while (rightEnum.MoveNext());
                        yield break;
                    }
                }
                else
                {
                    yield return onlyRightSelector(rightEnum.Current);

                    if (!rightEnum.MoveNext())
                    {
                        do
                        {
                            yield return onlyLeftSelector(leftEnum.Current);
                        } while (leftEnum.MoveNext());
                        yield break;
                    }
                }
            }
        }
    }
公共静态IEnumerable MergeJoin\u OneToOne(
IEnumerable leftCollection,
IEnumerable rightCollection,
Func比较,
Func onlyLeftSelector,
Func onlyRightSelector,
Func(两个选择器)
{
返回MergeJoin_OneToOne_Impl(leftCollection、rightCollection、comparison、onlyLeftSelector、onlyRightSelector、bothSelector);
}
静态IEnumerable MergeJoin\u OneToOne\u Impl(
IEnumerable leftCollection,
IEnumerable rightCollection,
Func比较,
Func onlyLeftSelector,
Func onlyRightSelector,
Func(两个选择器)
{
如果(leftCollection==null)抛出新的ArgumentNullException(“leftCollection”);
如果(rightCollection==null)抛出新的ArgumentNullException(“rightCollection”);
如果(comparison==null)抛出新的ArgumentNullException(“comparison”);
如果(onlyLeftSelector==null)抛出新的ArgumentNullException(“onlyLeftSelector”);
如果(onlyRightSelector==null)抛出新的ArgumentNullException(“onlyRightSelector”);
如果(bothSelector==null)抛出新的ArgumentNullException(“bothSelector”);
使用(var leftEnum=leftCollection.GetEnumerator())
使用(var rightEnum=righcollection.GetEnumerator())
{
如果(!leftEnum.MoveNext())
{
而(rightEnum.MoveNext())只返回RightSelector(rightEnum.Current);
屈服断裂;
}
如果(!rightEnum.MoveNext())
{
做
{
仅返回YOULT LEFTSELECTOR(leftEnum.Current);
}while(leftEnum.MoveNext());
屈服断裂;
}
while(true)
{
int cmp=比较(leftEnum.Current、righenum.Current);
如果(cmp==0)
{
返回两个选择器(leftEnum.Current、rightEnum.Current);
如果(!leftEnum.MoveNext())
{
while(rightEnum.MoveNext())
{
仅返回RightSelector(rightEnum.Current);
}
屈服断裂;
}
如果(!rightEnum.MoveNext())
{
做
{
仅返回YOULT LEFTSELECTOR(leftEnum.Current);
}while(leftEnum.MoveNext());
屈服断裂;
}
}
否则如果(cmp<0)
{
仅返回YOULT LEFTSELECTOR(leftEnum.Current);
如果(!leftEnum.MoveNext())
{
做
{
仅返回RightSelector(rightEnum.Current);
}while(rightEnum.MoveNext());
屈服断裂;
}
}
其他的
{
仅返回RightSelector(rightEnum.Current);
如果(!rightEnum.MoveNext())
{
做
{
仅返回YOULT LEFTSELECTOR(leftEnum.Current);
}while(leftEnum.MoveNext());
屈服断裂;
}
}
}
}
}
出于性能原因,您将此函数专用于
IList
元素。去掉迭代器,使用两个整数表示列表中的当前位置。在遍历列表时,A忽略lt为0且与B相同的元素

速度提升将来自多方面的改进:对象分配是grea
    static void Main(string[] args)
    {
        double[] input = { 1.00, 2.92, -2.92, 3.00, 7.56, -7.56, 8.00, -100.93, -40.56 };
        IEnumerable<int> intsWithouDuplicates = input.Where(d => !input.Contains(-d)).Select(d => (int)(d * 100)).OrderBy(i => i);
        var listA = intsWithouDuplicates.Where(i => i >= 0);
        var listB = intsWithouDuplicates.Where(i => i < 0);

        listA.ToList().ForEach(Console.WriteLine);
        Console.WriteLine();
        listB.ToList().ForEach(Console.WriteLine);
        Console.ReadKey();
    }
      decimal[] input = new decimal[] { -6, 1, 2, 3, -1, 2, 2, -2, 6, 7, -4, 4, -7, 8, -4 };
      Stack<decimal> st = new Stack<decimal>();

      IEnumerable<decimal> sorted = input.OrderBy(X => X > 0 ? X : -X);

      foreach (decimal item in sorted)
        if (st.Any() && st.Peek() == -item)
          st.Pop();
        else
          st.Push(item);

      decimal[] pos = st.Where(X => X >= 0).ToArray();
      decimal[] neg = st.Where(X => X < 0).ToArray();