我有两个迭代器,必须合并成一个结果。
以下是数据示例:
ArrayIterator Object
(
[storage:ArrayIterator:private] => Array
(
[0] => Array
(
[period] => 04/04/2012 16:00:00
[bl_subs] => 1
[bl_unsubs] => 1
[bl_block_total] => 1
)
[1] => Array
(
[period] => 04/04/2012 17:00:00
[bl_subs] => 1
[bl_unsubs] => 2
[bl_block_total] => 0
)
[2] => Array
(
[period] => 04/04/2012 18:00:00
[bl_subs] => 0
[bl_unsubs] => 0
[bl_block_total] => -1
)
[3] => Array
(
[period] => 04/04/2012 19:00:00
[bl_subs] => 2
[bl_unsubs] => 0
[bl_block_total] => -2
)
[4] => Array
(
[period] => 04/04/2012 20:00:00
[bl_subs] => 2
[bl_unsubs] => 0
[bl_block_total] => 1
)
)
)
ArrayIterator Object
(
[storage:ArrayIterator:private] => Array
(
[0] => Array
(
[period] => 04/04/2012 15:00:00
[bl_avg] => 5
[bl_full] => 0
)
[1] => Array
(
[period] => 04/04/2012 17:00:00
[bl_avg] => 0
[bl_full] => 7
)
[2] => Array
(
[period] => 04/04/2012 18:00:00
[bl_avg] => 1
[bl_full] => 0
)
)
)
ArrayIterator Object
(
[storage:ArrayIterator:private] => Array
(
[0] => Array
(
[period] => 04/04/2012 15:00:00
[bl_subs] => 0
[bl_unsubs] => 0
[bl_avg] => 5
[bl_full] => 0
[bl_block_total] => 0
)
[1] => Array
(
[period] => 04/04/2012 16:00:00
[bl_subs] => 1
[bl_unsubs] => 1
[bl_avg] => 0
[bl_full] => 0
[bl_block_total] => 1
)
[2] => Array
(
[period] => 04/04/2012 17:00:00
[bl_subs] => 1
[bl_unsubs] => 2
[bl_avg] => 0
[bl_full] => 7
[bl_block_total] => 0
)
[3] => Array
(
[period] => 04/04/2012 18:00:00
[bl_subs] => 0
[bl_unsubs] => 0
[bl_avg] => 1
[bl_full] => 0
[bl_block_total] => -1
)
[4] => Array
(
[period] => 04/04/2012 19:00:00
[bl_subs] => 2
[bl_unsubs] => 0
[bl_avg] => 0
[bl_full] => 0
[bl_block_total] => -2
)
[5] => Array
(
[period] => 04/04/2012 20:00:00
[bl_subs] => 2
[bl_unsubs] => 0
[bl_avg] => 0
[bl_full] => 0
[bl_block_total] => 1
)
)
)
current()和next()使用内部数组指针。最佳答案
如果两个迭代器都是排序的,您可以缓存它们,比较每个迭代中哪个优先(如果不相等),并处理那个迭代。如果相等,则对两者进行同等处理。
不平等:
$it1[[period] => 04/04/2012 16:00:00] > $it2[[period] => 04/04/2012 15:00:00]
=> process $it2 data:
[period] => 04/04/2012 15:00:00
[bl_avg] => 5
[bl_full] => 0
as current():
[period] => 04/04/2012 15:00:00
[bl_subs] => 1
[bl_unsubs] => 1
[bl_avg] => 5
[bl_full] => 0
[bl_block_total] => 1
+ $it2->next();
$it2[0] (15:00))[bl_subs => 1]、[bl_unsubs] => 1和[bl_block_total] => 1中不存在的元素是如何产生的。这是默认值吗?$it1[[period] => 04/04/2012 17:00:00] == $it2[[period] => 04/04/2012 17:00:00]
=> process $it1 and $it2 data:
$it1:
[period] => 04/04/2012 17:00:00
[bl_subs] => 1
[bl_unsubs] => 2
[bl_block_total] => 0
$it2:
[period] => 04/04/2012 17:00:00
[bl_avg] => 0
[bl_full] => 7
as current():
[period] => 04/04/2012 17:00:00
[bl_subs] => 1
[bl_unsubs] => 2
[bl_avg] => 0
[bl_full] => 7
[bl_block_total] => 0
+ $it1->next(); $it2->next();
Iterator,所以它被很好的封装了。因为给定的信息是有限的,所以我创建了一个简化的例子,将日期减少到问题域:一次迭代两个迭代器。如果两个迭代器相等,则返回两者。如果不相等,则返回比较两者时的第一个。$ar1 = array('04/04/2012 16:00:00', '04/04/2012 17:00:00', '04/04/2012 18:00:00', '04/04/2012 19:00:00', '04/04/2012 20:00:00');
$ar2 = array('04/04/2012 15:00:00', '04/04/2012 17:00:00', '04/04/2012 18:00:00');
$it1 = new ArrayIterator($ar1);
$it2 = new ArrayIterator($ar2);
usortDocs的工作方式进行比较:一个函数比较a和b,并基于两者返回一个整数值:strcmp/**
* Get Comparison-Value of an Iterator
*
* @param Iterator $iterator
* @return string
*/
$compareValue = function(Iterator $iterator) {
$value = $iterator->current();
sscanf($value, '%d/%d/%d %s', $month, $day, $year, $timeISO);
$dateISO = sprintf('%04d-%02d-%02d %s', $year, $month, $day, $timeISO);
return $dateISO;
};
/**
* Compare two Iterators by it's value
*
* @param Iterator $a
* @param Iterator $b
* @return int comparison result (as of strcmp())
*/
$compareFunction = function(Iterator $a, Iterator $b) use ($compareValue) {
return strcmp($compareValue($a), $compareValue($b));
};
strcmp字符串比较函数,并使用$compareValue函数获取用于比较的字符串。/**
* Usage
*/
$it = new MergeCompareIterator($compareFunction, array($it1, $it2));
foreach ($it as $index => $values) {
printf("Iteration #%d:\n", $index);
foreach ($values as $iteratorIndex => $value) {
printf(" * [%d] => %s\n", $iteratorIndex, $value);
}
}
Iteration #0:
* [1] => 04/04/2012 15:00:00
Iteration #1:
* [0] => 04/04/2012 16:00:00
Iteration #2:
* [0] => 04/04/2012 17:00:00
* [1] => 04/04/2012 17:00:00
Iteration #3:
* [0] => 04/04/2012 18:00:00
* [1] => 04/04/2012 18:00:00
Iteration #4:
* [0] => 04/04/2012 19:00:00
Iteration #5:
* [0] => 04/04/2012 20:00:00
$defaults = array('bl_subs' => 0, ...);
foreach ($it as $values) {
array_unshift($values, $default);
$value = call_user_func_array('array_merge', $values);
}
MergeCompareIterator的用法。实现是相当直接的,到目前为止这一个还没有缓存排序/当前迭代器,如果您想改进它,我将此作为一个练习。<?php
/**
* @link http://stackoverflow.com/q/10024953/367456
* @author hakre <http://hakre.wordpress.com/>
*/
$ar1 = array('04/04/2012 16:00:00', '04/04/2012 17:00:00', '04/04/2012 18:00:00', '04/04/2012 19:00:00', '04/04/2012 20:00:00');
$ar2 = array('04/04/2012 15:00:00', '04/04/2012 17:00:00', '04/04/2012 18:00:00');
$it1 = new ArrayIterator($ar1);
$it2 = new ArrayIterator($ar2);
/**
* Get Comparison-Value of an Iterator
*
* @param Iterator $iterator
* @return string
*/
$compareValue = function(Iterator $iterator)
{
$value = $iterator->current();
sscanf($value, '%d/%d/%d %s', $month, $day, $year, $timeISO);
$dateISO = sprintf('%04d-%02d-%02d %s', $year, $month, $day, $timeISO);
return $dateISO;
};
/**
* Compare two Iterators by it's value
*
* @param Iterator $a
* @param Iterator $b
* @return int comparison result (as of strcmp())
*/
$compareFunction = function(Iterator $a, Iterator $b) use ($compareValue)
{
return strcmp($compareValue($a), $compareValue($b));
};
/**
* Iterator with a comparison based merge-append strategy over 0 or more iterators.
*
* Compares 0 or more iterators with each other. Returns the one that comes first
* and any additional one that is equal to the first as an array of their current()
* values in this current().
* next() forwards all iterators that are part of current().
*/
class MergeCompareIterator implements Iterator
{
/**
* @var Iterator[]
*/
private $iterators;
/**
* @var callback
*/
private $compareFunction;
/**
* @var int
*/
private $index;
/**
* @param callback $compareFunction (same sort of usort()/uasort() callback)
* @param Iterator[] $iterators
*/
public function __construct($compareFunction, array $iterators = array())
{
$this->setCompareFunction($compareFunction);
foreach ($iterators as $iterator) {
$this->appendIterator($iterator);
}
}
/**
* @param callback $compareFunction
*/
public function setCompareFunction($compareFunction)
{
if (!is_callable($compareFunction)) {
throw new InvalidArgumentException('Compare function is not callable.');
}
$this->compareFunction = $compareFunction;
}
public function appendIterator(Iterator $it)
{
$this->iterators[] = $it;
}
public function rewind()
{
foreach ($this->iterators as $it) {
$it->rewind();
}
$this->index = 0;
}
/**
* @return Array one or more current values
* @throws RuntimeException
*/
public function current()
{
$current = array();
foreach ($this->getCurrentIterators() as $key => $value) {
$current[$key] = $value->current();
}
return $current;
}
/**
* @return Iterator[]
*/
private function getCurrentIterators()
{
/* @var $compareFunction Callable */
$compareFunction = $this->compareFunction;
$iterators = $this->getValidIterators();
$r = uasort($iterators, $compareFunction);
if (FALSE === $r) {
throw new RuntimeException('Sorting failed.');
}
$compareAgainst = reset($iterators);
$sameIterators = array();
foreach ($iterators as $key => $iterator) {
$comparison = $compareFunction($iterator, $compareAgainst);
if (0 !== $comparison) {
break;
}
$sameIterators[$key] = $iterator;
}
ksort($sameIterators);
return $sameIterators;
}
/**
* @return Iterator[]
*/
private function getValidIterators()
{
$validIterators = array();
foreach ($this->iterators as $key => $iterator) {
$iterator->valid() && $validIterators[$key] = $iterator;
}
return $validIterators;
}
/**
* @return int zero based iteration count
*/
public function key()
{
return $this->index;
}
public function next()
{
foreach ($this->getCurrentIterators() as $iterator) {
$iterator->next();
}
$this->index++;
}
public function valid()
{
return (bool)count($this->getValidIterators());
}
}
/**
* Usage
*/
$it = new MergeCompareIterator($compareFunction, array($it1, $it2));
foreach ($it as $index => $values) {
printf("Iteration #%d:\n", $index);
foreach ($values as $iteratorIndex => $value) {
printf(" * [%d] => %s\n", $iteratorIndex, $value);
}
}
关于php - php通过其值之一合并两个或多个ArrayIterators,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10024953/
Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题
我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代
尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
我正在使用puppet为ruby程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这
我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是
我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search
我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2
我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这