您有自己的“杂项工具”库吗?您最为哪一部分感到骄傲?[关闭]


32

我知道我们许多人使用经常使用的工具和实用程序来维护自己的小型个人图书馆。

我从16岁起就拥有我的,所以它的规模已经发展到相当可观的水平。此后,我写的一些内容已添加到框架中。我在LINQ之前就编写了自己的表达树的小实现,用于遗传算法,这在当时我很喜欢,并为此感到自豪-当然,现在它已经毫无用处了。但是最近我一直在研究它并升级到.NET 4.0,并重新引起了人们的兴趣。

所以我很好奇您使用库的目的。也许我们可以得到一些有用的小片段的好主意,并在我们自己之间分享。

所以我的问题是:

  • 您是否有其他实用程序库?
  • 您最为哪一部分感到自豪,为什么?

如果您愿意,请提供代码示例 :-)


似乎没有人赞成答案……
Joey Adams 2010年

@Joey Adams对吗?目前有17个问题票和6个总计回答票。
妮可

我没有真正看到值得推荐的答案。投票对他们意味着什么?问题的性质是,答案只会是“哦,很好”。一种反应,然后要么全部投票,要么一无所有。(我不喜欢upvoting每一个答案,只是因为它的存在,如果不出意外,我出票:P)
亚当李尔

@Anna Lear,好吧,您很抱歉:)
Nicole 2010年

3
任何体面的实用程序都应该放在github上并与世界共享。如果它确实是好的,那么将其隐藏起来是没有意义的。
工作

Answers:


27

没有。

我已经看到了十几个开发人员的噩梦,他们都在项目中添加了自己的小“ util.h”样式库,并使它变成了功能命名和行为不一致的巨大混乱。很像PHP。因此,出于这个原因,我避免这样做。

我避免使用编程环境来做到这一点,因为编程环境会尽可能为我提供几乎所有我需要的工具和库,例如C#和python。


7
我经常出于组织目的重写我的图书馆。
Maxpm 2010年

3
utils软件包变成噩梦的情况并不意味着一切都不好。我看不到如何避免它,并且因此没有更多的代码重复。因此,测试质量较差,效率较低。
妮可

2
@Renesis:utils软件包与goto语句一样灾难性。当然,它本身并没有那么糟糕,但似乎迟早总会变成灾难。至于代码复制,如果您发现自己几乎在所有项目中都执行了类似的任务,那么对于诸如python或C#之类的事情,其他人也可能也在执行,并且那时可能已经在标准库中了。
whatsisname 2010年

6
以我的经验,拥有自己的库的工程师会喜欢在系统提供的库之前使用它,因此拥有个人库不是一个好习惯。我曾经有一个人绝对确信他的“ strlen”功能比编译器提供的功能更快因为他写了它。它简单地演示了几条内联的汇编指令多么令人震惊,让他承认也许其他人可以做得更好。
JBRWilkinson 2010年

4
@JBRWilkinson您的观点是正确的。并非每个程序员都适合开发通用代码。
妮可

15

智能格式

我最喜欢的实用程序是我编写的实用程序-一种简单的字符串生成器/格式化程序,可以很容易地将数据转换为具有正确语法的字符串。

例如,大多数程序员都从模板构建文本: "There are {0} items remaining" 但这会导致语法错误:"There are 1 items remaining"

因此,SmartFormat可让您编写:"There {0:is|are} {0} item{0:|s} remaining"

您只需替换String.Format(...)Smart.Format(...)就可以了!

SmartFormat代码是开源:http://github.com/scottrippey/SmartFormat/wiki


这使我想起了所使用的格式java.text.MessageFormat
barjak 2010年

@barjak有趣!我花了很长时间研究“条件”格式,直到现在再也找不到类似的东西! MessageFormat具有ChoiceFormat允许惊人的相似语法的类!文档中的示例: "There {0,choice,0#are no files|1#is one file|1<are {0,number,integer} files}."。感谢您提及此参考。
Scott Rippey

@barjak只是为了证实我的观点,SmartFormat还有更多功能!条件格式适用于任何数据类型,例如bool,日期,时间跨度和对象。它还支持高级运算符,例如"{Count:<0?negative|=5?five|>50&<100?large|other}"。它具有反射性(即"There are {items.Length} items",可以格式化数组项和时间跨度。此外,它具有支持更多功能的插件模型。)
Scott Rippey

实际上,它似乎很强大。数组格式化令人费解。
barjak

@barjak:是的,数组格式化非常有用!看看这个例子:Smart.Format("There are {0.Count} files: {0:'{}'|, |, and }.", files);会产生"There are 3 files: 'a.txt', 'b.txt', and 'c.txt'."。没有它,我无法想象“本地化”。
Scott Rippey

7

K组合器(C#,Scala)

我经常在Ruby中使用K组合器,当通过副作用而不是返回值执行折叠操作时,大多数情况下是在折叠中使用,例如以下示例:

some_collection.reduce(Hash.new(0)) {|acc, el| acc[el] += 1 }

这将计算每个元素在中出现的频率some_collection。不幸的是,它实际上并不起作用,因为该块必须在每次迭代时返回累加器的新值,但是在Ruby中,赋值运算为赋值。

因此,您必须像这样精确地返回累加器的新值:

some_collection.reduce(Hash.new(0)) {|acc, el| acc[el] += 1; acc }

但是我发现这种显式的排序很丑陋,使用折叠功能。使用K组合器(Object#tap在Ruby中称为):

some_collection.reduce(Hash.new(0)) {|acc, el| acc.tap { acc[el] += 1 }}

我已经在C#中错过了几次(主要是由于某种原因,集合变量(例如List.Addreturn void而不是this)和Scala),所以我解决了这个问题:

namespace GenericExtensions
{
    public static class GenericExtensions
    {
        public static T Tap<T>(this T o, Action<T> f)
        {
            Contract.Requires(o != null);
            Contract.Requires(f != null);

            f(o);
            return o;
        }

        public static T Tap<T>(this T o, Action f)
        {
            Contract.Requires(o != null);
            Contract.Requires(f != null);

            f();
            return o;
        }
    }
}

在Scala中:

class Tap[T](o: T) {
  def tap(f: T => Unit) = { f(o); o }
  def tap(f: => Unit) = { f; o }
}

object Implicits { implicit def any2Tap[T](o: T) = new Tap(o) }

身份功能(Ruby)

我在Ruby中缺少的东西是一种访问身份函数的好方法。Haskell在名称下提供身份功能id,Scala 名称下提供Scala identity。这样一来,您可以编写如下代码:

someCollection.groupBy(identity)

Ruby中的等效项是

some_collection.group_by {|x| x }

不会完全从舌头上滑下来吗?

解决方法是

IDENTITY = -> x { x }

some_collection.group_by(&IDENTITY)

ForEach(.NET)

C#中另一个非常缺失的方法:

namespace IEnumerableExtensions
{
    public static class IEnumerableExtensions
    {
        public static void ForEach<T>(this IEnumerable<T> xs, Action<T> f)
        {
            Contract.Requires(xs != null);
            Contract.Requires(f != null);

           foreach (var x in xs) f(x);
        }
    }
}

3
我认为您的最后一个示例是经过精心设计的决策。Action隐含的概念与LINQ的设计原则背道而驰。
ChaosPandion 2010年

1
@ChaosPandion:这和LINQ有什么关系?
约尔格W¯¯米塔格

@JörgW Mittag- IEnumerable为LINQ添加了扩展名。
ChaosPandion 2010年

2
@ChaosPandion:我还是不明白。ForEach不是LINQ运算符。为什么只适用于LINQ运算符的限制适用于ForEach而不是LINQ运算符的限制?为何为什么禁止副作用IEnumerable.ForEach却允许List.ForEach呢?另外,为什么禁止副作用IEnumerable.ForEach但允许副作用foreach
约尔格W¯¯米塔格

@JörgW Mittag-我的意思是,扩展中缺少它是设计决定。考虑到它是可变类型,List<T>具有的事实ForEach是合理的。
ChaosPandion 2010年

6

我有一个Java类型转换器。具有公开签名

public static <T> T convert(Object sourceValue, Class<T> destinationType)

并尽最大努力将源值转换为目标类型。本质上,它使您可以在静态类型的语言中进行动态键入:-)

实际上,对于装箱的数字类型很有用。你不能把期望放在Integer哪里Long是多么令人烦恼?没问题,只需将其转换即可。或者,如果您的函数需要一个double,但又要null放一个呢?NPE Kaboom。但是经过它convert,你会得到一个NaN


有趣的解决方案。我一直认为Long应该扩展Integer。但是即使那样,您仍然会遇到自动装箱问题(据我所知,自动装箱无法与继承一起工作)。另外,+ 1 NaN支持。
妮可

NaN非常好 太糟糕了,整数没有这种东西。我已经习惯Integer.MIN_VALUE了。与默认值0不同,它通常“足够怪异”以引起注意。我不知道为什么auto(un)boxing不能(Double) null视为NaN。恕我直言,这是显而易见的正确解决方案。
Joonas Pulakka 2010年

6

在我编写的混杂代码中,大多数好东西现在都在CCAN中,而其余​​的我倾向于在现有的开源项目中找到更好的版本。最近,我发现自己编写的通用“ misc”代码越来越少,倾向于编写此类代码的特定于应用程序的变体,或者编写自己可以释放的通用模块。

C

这是我已使用多次的函数和typedef。对于需要定时的应用程序,在简单性方面很难超过毫秒:

#include <stdint.h>
#include <sys/time.h>

typedef int64_t msec_t;

static msec_t time_ms(void)
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return (msec_t)tv.tv_sec * 1000 + tv.tv_usec / 1000;
}

以及我倾向于一遍又一遍地使用的其他各种C函数:

/* Remove a trailing newline, if present. */
void chomp(char *buffer)
{
    if (!*buffer)
        return;

    while (*buffer)
        buffer++;

    if (buffer[-1] == '\n')
        buffer[-1] = 0;
}

/*
 * Skip whitespace, update the pointer, and return it.
 * Example:
 *
 * switch (*skipSpace(&s)) {
 *     case '\0':
 *         ...
 *     case '(':
 *         ...
 */
const char *skipSpace(const char **sptr)
{
    const char *s = *sptr;
    while (isspace(*s))
        s++;
    *sptr = s;
    return s;
}

/* Scramble an array of items uniformly. */
void scramble(void *base, size_t nmemb, size_t size)
{
    char *i = base;
    char *o;
    size_t sd;
    for (;nmemb>1;nmemb--) {
        o = i + size*(rand()%nmemb);
        for (sd=size;sd--;) {
            char tmp = *o;
            *o++ = *i;
            *i++ = tmp;
        }
    }
}

哈斯克尔

Haskell的nub :: (Eq a) => [a] -> [a]函数为O(n²),因为根据其类型签名,它只能测试两个元素是否相等。一个简单的O(n log n)替代方法是map head . group . sort,但是它需要在产生输出之前强制执行整个输入列表,而nub可以立即开始产生输出。以下是O(n log n)的替代方案,nub该方案收集a中已经看到的项目Data.Set

module Nub (nub') where

import Prelude
import Data.Set (empty, member, insert)

nub' :: Ord a => [a] -> [a]
nub' xs = loop xs empty where
    loop [] _ = []
    loop (x:xs) set =
        if x `member` set
            then loop xs set
            else x : loop xs (insert x set)

在Haskell中,我使用的替代品sequencemapMforMreplicateM,和filterM。这些操作都会生成一个列表,但是只有在操作完整完成后才能使用该列表(如果您使用的是像IO这样的严格monad)。替代方案以相反的方式建立了列表,而不是形成笨拙的塔楼,我通过基准测试发现,至少在GHC模式下,它更快。

sequence' :: Monad m => [m a] -> m [a]
sequence' ms = loop ms [] >>= return . reverse where
    loop []     xs = return xs
    loop (m:ms) xs = do
        x <- m
        loop ms (x:xs)

mapM' :: Monad m => (a -> m b) -> [a] -> m [b]
mapM' f xs = sequence' $ map f xs

forM' :: Monad m => [a] -> (a -> m b) -> m [b]
forM' = flip mapM'

replicateM' :: Monad m => Int -> m a -> m [a]
replicateM' n x = sequence' (replicate n x)

filterM' :: Monad m => (a -> m Bool) -> [a] -> m [a]
filterM' pred xs = loop xs [] >>= return . reverse where
    loop []     xs' = return xs'
    loop (x:xs) xs' = do
        keep <- pred x
        loop xs (if keep then (x:xs') else xs')

注:sequence_mapM_forM_,和replicateM_功能仍然是一个更好的选择,如果你没有在结果列表感兴趣。


CCAN +1,尽管我可能会觉得有点偏颇:)
Tim Post

4

我最终用没有它的语言实现了split / join ala Perl。

我还用C重新实现了atoi和itoa的次数比我想的要多(嵌入式系统垃圾)。


4

没有。

我用Java编写大部分代码,最佳实践是重用Apache Commons库和类似项目中的“ utils”。

如果您对此持客观态度,那么在少数情况下,您自己的“实用程序”集合将大大改善其他人已经做的事情。而且,如果这不是一个改进,那么您的utils库可能会浪费开发时间,并且会给以后的维护者带来麻烦/负担。


3

我使用Java执行了一些日期操作,然后开始使用JodaTime,因为我听说过有关它的好东西,并将其包含在Java 7中(不确定是否仍然存在,但即使不是,也仍然如此)非常值得使用imho)。

它通过大约三个链接的方法调用将50+行类转换为一行。

出于好奇,它涉及获取过去n周的每一天的日期:例如10周前的星期一的销售数字,等等)。

这是其中的一部分

public static DateTime getDayPreviousWeek(DateTime dt, DayOfWeek dayOfWeek, int n_weeks) {
       return dt.minusWeeks(n_weeks).dayOfWeek().setCopy(dayOfWeek.getDayAsString());
}

java有扩展方法吗?
Kugel 2010年

不,但我认为可能是在第7版中获得它们
NimChimpsky 2010年

2

我总是有某种utils软件包,即使使用Java也是如此,但是我的PHP utils集合使用得最多。Java有很多好的库,因此我要么已经在项目中包含一个库,要么只需要自己设计一些缺少的utils。PHP库对于我来说想做太多了,想将它们包含在我的项目中。

我有点喜欢PHP的此功能,并在StackOverflow的帮助下进行了完善 ...

function getValueFromDotKey(&$context, $name) {
    $pieces = explode('.', $name);
    foreach ($pieces as $piece) {
        if (!is_array($context) || !array_key_exists($piece, $context)) {
            // error occurred
            return null;
        }
        $context = &$context[$piece];
    }
    return $context;
}

它类似于Apache的Java BeanUtils,我将其用于类似目的,为模板语言的表单元素提供了一个单键,该键可以获取/设置源数组中的嵌套值:

$source = array('a' => array('b' => 5));

$val = getValueFromDotKey($source, 'a.b');

当然,作为PHP,我想保持的方法轻量级越好,所以它不是相当的多特征为BeanUtils的;)


2

Scala标准库缺少一些最常用的高阶函数。

我最需要的两个此类功能:

// #1: unfold
def unfold[T, R](init: T)(f: T => Option[(R, T)]): List[R] = f(init) match {
  case None => Nil
  case Some(r, v) => r :: unfold(v)(f)
}

// #2: zipWith
def zipWith[A, B, C](xs: List[A], ys: List[B])(f: (A, B) => C): List[C] = {
  (xs, ys).zipped.map(f)
}

1

目前没有。当我使用C语言时,我只有一个,但是现在我使用Java,考虑到所有可用的标准库以及来自Apache项目的所有好处,它不再有意义。

我的C库中有用的东西之一是快速脏的有限状态机实现,该实现允许只用两个字符串和一个字符串数组定义一个有限状态机。它可以用来根据规则检查字符串(例如“必须长4..6个字符,第一个字母是字母,其余数字”),但是正则表达式的可用性使这一点变得毫无意义。



1

我发现我在django中编写了很多相同的代码,先做这个普通的事情,然后做这个普通的事情,最后做那个普通的事情。基本上是从数据库中获取一项或多项,或者保存表单的结果。

如果这些事情中的每一项仅在视图中发生一次,那么我可以使用django通用视图。不幸的是,这些并不是真正可组合的,我需要按顺序做几件事。

因此,我去写了一个更为通用的视图库,该库首先通过从相关查询集(或其他查询集)构建动作列表,然后将列表包装到视图中来工作。

我仍然必须手动编写一些视图,但是这些视图通常足够复杂,以至于其中没有太多可重用的视图。所有样板文件都可以在通用视图或视图装饰器(通常是经过修饰的通用视图)中放到其他地方。由于某些通用处理程序可以完成其他所有操作,因此通常最终只占我编写的处理程序的10%。


1

是的,但仅适用于特定领域的习惯用语结构(例如特定于游戏对象的容器)。

由于它是简单的实用工具,而不是任何复杂的工具,因此我对此并不感到骄傲。无论如何,我现在是唯一的用户,因此没有什么值得骄傲的。


1

基于STL sort和仿函数模板的C ++间接排序。

在许多项目中,对间接排序的需求(其中期望的输出是排序数据所产生的排列索引,而不是排序后的数据本身)的需求出现了很多次。我一直想知道为什么STL没有为其提供实现。

另一个是C ++循环向量,其中正负索引与向量大小成模(这样,任何整数值都是向量的有效索引)。


-4

我在Comp进行Java开发时写了一个小的utils程序包。高中科学课。我为我的随机数生成器感到最自豪。

/**
* Returns a random integer.
*
* @returns    int    Random integer
*/
public static int getRandom()
{
    return 4; // Chosen by a fair dice roll.
              // Guaranteed to be random.
}

支撑我的灵感。


12
来吧,xkcd ....
黑暗之夜2010年

2
来吧,没关系。
乔什·K

1
以您当前的投票数为-2,我认为这确实很重要...
user7676

8
抄袭是奉承的最高形式,除非显而易见。
Maxpm 2010年

5
好吧,向下投票按钮说:“这个答案没有用”。我想需要一个附加按钮:“ ...但一定很有趣”
skajfes 2010年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.