speelpenning/binary-search-collection

为 Laravel 的集合扩展了二分搜索支持。

v1.0 2016-04-15 15:04 UTC

This package is auto-updated.

Last update: 2024-09-08 17:31:15 UTC


README

Build Status codecov.io Latest Stable Version Latest Unstable Version License

当处理包含具有唯一标识符的对象的大型数据集时,此软件包非常有用。

入门

要求

  • illuminate/support: >= 5.0

安装

使用 Composer 引入软件包

composer require speelpenning/binary-search-collection

使用方法

如果您有以不同格式(如 csv 和 XML)存储的结构化数据,并且需要合并数据以生成报告,您只需定义一些模型并创建一个返回包含模型的集合的读取器。

示例用例

假设我们有以下文件

  • 一个包含 200,000 个产品的 XML 文件(产品编号、描述等)
  • 一个包含 70,000 个价格(产品编号、含税价格、净价、列表价格)的 csv 价格表

为了向“我们的客户”发送价格表,我们需要创建一个包含产品编号、描述、列表价格和含税价格的 csv 文件。

首先,我们需要两个模型,比如 Product 和 Price,它们包含文件中定义的属性。然后,我们为 XML 文件(即 ProductsReader)和 csv 文件(即 PriceReader)创建读取器。读取器在构造函数中接受二分排序集合,并用文件中的模型填充集合。读取器返回集合。

现在我们接近目标:为我们的客户生成 csv 价格表。为此,我们创建了一个写入器(例如 CustomerPriceListWriter),它在构造函数中接受两个读取器。写入器遍历包含 Price 模型的集合,同时使用二分搜索在另一个集合中查找 Product 记录。然后将两个模型的数据合并,并将带有客户价格的数据写入 csv 文件。

<?php

class CustomerPriceListWriter
{
    /**
     * @var ProductReader
     */
    protected $productReader;

    /**
     * @var PriceReader
     */
    protected $priceReader;

    /**
     * Create a new customer price list writer instance.
     *
     * @param ProductReader $productReader
     * @param PriceReader $priceReader
     */
    public function __construct(ProductReader $productReader, PriceReader $priceReader)
    {
        $this->productReader = $productReader;
        $this->priceReader = $priceReader;
    }


    protected function write($productsFilename, $pricesFilename, $targetFilename = null)
    {
        // First we read the products and prices file, which both
        // return a collection that supports binary search.
        $products = $this->productReader->read($productsFilename);
        $prices = $this->priceReader->read($pricesFilename);

        // Prepare the array with CSV lines.
        $csv = [$this->toCsv([
            'Product Number',
            'Description',
            'List price',
            'Your price'
        ])];
        foreach ($prices as $price) {
            $product = $products->find($price->product_number);

            $csv[] = $this->toCsv([
                $product->product_number,
                $product->description,
                $price->list_price,
                $price->gross_price
            ]);
        }

        $targetFilename = is_null($targetFilename) ? 'customer-prices-'.date('YmdHis').'.csv' : $targetFilename;
        file_put_contents($targetFilename, implode("\n", $csv));
    }

    protected function toCsv(array $values)
    {
        foreach ($values as $key => $value) {
            $value[$key] = is_numeric($value) ? $value : "\"{$value}\"";
        }
        return implode(',', $values);
    }
}