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

推荐订阅源

Google DeepMind News
Google DeepMind News
Stack Overflow Blog
Stack Overflow Blog
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
T
The Blog of Author Tim Ferriss
博客园 - 叶小钗
N
Netflix TechBlog - Medium
腾讯CDC
C
Check Point Blog
P
Proofpoint News Feed
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI
S
SegmentFault 最新的问题
F
Fortinet All Blogs
美团技术团队
U
Unit 42
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 司徒正美
F
Full Disclosure
Recorded Future
Recorded Future
D
DataBreaches.Net
博客园 - 【当耐特】
Martin Fowler
Martin Fowler
J
Java Code Geeks
I
InfoQ
Y
Y Combinator Blog
A
About on SuperTechFans
AI
AI
爱范儿
爱范儿
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Forbes - Security
Forbes - Security
W
WeLiveSecurity
M
MIT News - Artificial intelligence
雷峰网
雷峰网
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Simon Willison's Weblog
Simon Willison's Weblog
Schneier on Security
Schneier on Security
The GitHub Blog
The GitHub Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
aimingoo的专栏
aimingoo的专栏
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
G
GRAHAM CLULEY
Know Your Adversary
Know Your Adversary
Latest news
Latest news
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
D
Docker
Recent Commits to openclaw:main
Recent Commits to openclaw:main
量子位
V2EX - 技术
V2EX - 技术
Project Zero
Project Zero

博客园 - 一味

[翻译]实例:在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();
        }
    }
}

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

欢迎指正。