惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

U
Unit 42
Microsoft Azure Blog
Microsoft Azure Blog
Engineering at Meta
Engineering at Meta
博客园 - 【当耐特】
人人都是产品经理
人人都是产品经理
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
WordPress大学
WordPress大学
有赞技术团队
有赞技术团队
Blog — PlanetScale
Blog — PlanetScale
酷 壳 – CoolShell
酷 壳 – CoolShell
aimingoo的专栏
aimingoo的专栏
Jina AI
Jina AI
小众软件
小众软件
博客园 - 叶小钗
MongoDB | Blog
MongoDB | Blog
大猫的无限游戏
大猫的无限游戏
博客园 - 聂微东
Y
Y Combinator Blog
云风的 BLOG
云风的 BLOG
I
InfoQ
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Martin Fowler
Martin Fowler
P
Proofpoint News Feed
MyScale Blog
MyScale Blog

博客园 - 一味

[翻译]实例:在Android调用WCF服务 基于LRU淘汰的高性能缓存 不是架构的架构之五:业务层的实现与自动代理(补充) 不是架构的架构之四:业务层的实现与自动代理 不是架构的架构之三:系统基础(2)主键选择和并发 不是架构的架构之二:系统基础(1) 不是架构的架构之一:总体思路 技术先行or业务先行 用了一年的键盘,记录下键盘磨损的状况 一个业务系统设计构想(一) 安装VS2008/.Net3.5/.Net3.0/.Net2.0sp1失败的解决办法 常用存储过程4(K310。3版本获取物流新单据的编码) 常用存储过程3(获取编码的上级编码和短编码) 常用存储过程2(获取编码级次) 常用存储过程1(获取字符串中的第一个数值) SQL Server中Rollup关键字使用技巧 Math.Round函数四舍五入的问题 SQL Server进程阻塞的检查和解决办法(转自好友Blog) 学习NHibernate的感悟和疑惑
一道算法题
一味 · 2010-08-04 · via 博客园 - 一味

设有两个对象定义如下:

//Item对象的内容分别代表一个存货对象的Id,名称,库存总数量

public class Item{public int ItemId;public string Name;public decimal CountQty;}

//ItemInventory对象的内容分别代表一个存货对象在各个仓库的库存数量

public class ItemInventory{public int ItemId,public int StockId,public decimal Qty;}

有两个数组对象ArrayA[Item]和ArrayB[ItemInventory]分别存储了两个对象列表,两个列表都已经分别按照ItemId字段进行排序,而ArrayA数组中的所有Item对象的CountQty的值为0,请用效率最高的算法将ItemInventory对象的Qty填入到相对应Item对象的CountQty中。

两个对象使用ItemId进行匹配,一个Item对象可能对应着多个ItemInventory对象。

提示:ArrayA和ArrayB都只需要循环一次。

这道题实际上是公司最近的一道内部考核题,为何需要效率最高的算法,源于本人在项目实践中遇到了类似场景。

两个数据实体如下:

 A

在业务中,需要提取出存货对象的基本信息,包含编码,名称之类,也包含了库存。

遇到这个问题时,通常的解决方案是写个SQL语句:

Select Item.ItemId,Number,Name,Sum(Inv.Qty) as CountQty From Item Left join ItemInventory as Inv on Item.ItemId=Inv.ItemId Group by Item.ItemId,Item.Number,Item.Name

但是由于两个表的数据量较大,关联的效率不高,客户界面有明显延时。

于是诞生了题中的问题,事实上,采用了本人认为的最高效率算法之后,提取两个记录级,然后通过算法合并比在SQL中关联查询快了一个数量级。

代码如下:

代码

using System;
using System.Collections.Generic;
using System.Diagnostics;namespace ArrayMerge
{
    
class Program
    {
        
class Item { public int ItemId; public string Name; public decimal CountQty;}
        
class ItemInventory { public int ItemId; public int StockId; public decimal Qty;}static Item[] _arrayA;
        
static ItemInventory[] _arrayB;static void CreateDemoData()
        {
            Console.WriteLine(
"开始创建演示对象");
            _arrayA 
= new Item[100000];
            List
<ItemInventory> listB = new List<ItemInventory>();
            Random r 
= new Random();
            
for (int i = 0; i < _arrayA.Length; i++)
            {
                _arrayA[i] 
= new Item { ItemId = i, Name = string.Format("测试对象-{0}", i), CountQty = 0 };//创建相对应的0~3个ItemInventory对象。
                for (int j = 0; j < 3; j++)
                {
                    
if (r.Next(100> 80break;
                    listB.Add(
new ItemInventory {ItemId = i, StockId = j, Qty = r.Next(1000)});
                }
            }
            _arrayB 
= listB.ToArray();

            Console.WriteLine(

"演示对象创建完毕,共创建了{0}个Item对象和{1}个ItemInventory对象", _arrayA.Length, _arrayB.Length);
        }
private delegate void DoSomething<T1, T2>(T1 a,T2 b);
        
private delegate int Compare<T1, T2>(T1 a, T2 b);static void MergeArray<T1,T2>(T1[] arrayA,T2[] arrayB,Compare<T1,T2> compare,DoSomething<T1,T2> mergeAction)
        {
            
int leftPosion = 0, rightPosion = 0;
            
while(leftPosion<arrayA.Length && rightPosion<arrayB.Length)
            {
                
int compareResult = compare(arrayA[leftPosion], arrayB[rightPosion]);
                
if(compareResult<0)
                {
                    leftPosion
++;
                    
continue;
                }
                
if(compareResult>0)
                {
                    rightPosion
++;
                    
continue;
                }
                
if(compareResult==0)
                {
                    mergeAction(arrayA[leftPosion], arrayB[rightPosion]);
                    rightPosion
++;
                    
continue;
                }
            }
        }
static void Main(string[] args)
        {
            CreateDemoData();
            Stopwatch sw 
= new Stopwatch();
            sw.Start();

            MergeArray(_arrayA, _arrayB,
                       (a, b) 

=> a.ItemId.CompareTo(b.ItemId),
                       (a, b) 
=> a.CountQty += b.Qty
                );
            sw.Stop();
            Console.WriteLine(
"数据合并完毕,共耗时(毫秒):{0}", sw.ElapsedMilliseconds);
            Console.ReadLine();
        }
    }
}

代码不复杂,一看就明白。只是为了增加算法的通用性,使用了泛型和方法委托。

欢迎指正。