独自の「その他のユーティリティ」ライブラリはありますか?あなたが最も誇りに思う部分は何ですか?[閉まっている]


32

私たちの多くは、頻繁に使用するツールとユーティリティを使用して、独自の小さな個人ライブラリを維持していることを知っています。

私は16歳の時から私のものを持っているので、かなりの規模に成長しました。私が書いたもののいくつかは、その後フレームワークに追加されました。LINQのかなり前に、遺伝的アルゴリズムで使用する式ツリーの独自の小さな実装を作成しました。しかし最近、私はそれを経験して.NET 4.0にアップグレードし、興味を再燃させました。

だから私はあなたがあなたのライブラリを何のために使うのか興味があります。たぶん、便利な小さなスニペットのためにいくつかのクールなアイデアを得て、それらを私たちの間で共有することができました。

だから私の質問は:

  • その他のユーティリティライブラリはありますか?
  • あなたが最も誇りに思っている部分とその理由は?

必要に応じてコードの例を挙げてください :-)


誰も...答えをupvotingているように見えるん
ジョーイ・アダムス

@Joey Adamsそうですか?現在、17の質問票と6つの合計回答票。
ニコール

賛成に値する答えは本当に見当たりません。彼らにとって、賛成票とはどういう意味ですか?質問の性質は、答えが「ああ、いいね」となるようなものです。一種の反応であり、それはすべてを支持するか、まったく支持しないかのいずれかです。(そして、私はそれがちょうど原因すべての答えをupvoting好きではない何もない場合は、私が投票のうちだ:P)
アダムリア

@アンナリア、わかりました、あなたは言い訳されています:)
ニコール

3
適切なユーティリティはgithubに配置し、世界中で共有する必要があります。本当に良い場合は、隠しておくのは意味がありません。
ジョブ

回答:


27

いや

多数の開発者がプロ​​ジェクトに独自の小さな「util.h」スタイルのライブラリを追加し、一貫性のない関数の命名と動作の巨大な混乱に変えてしまうという悪夢のような効果を見てきました。PHPによく似ています。そのため、私はそれを避けています。

C#やpythonなど、可能な限り事前に必要なほぼすべてのツールとライブラリを提供するプログラミング環境を使用することで、これを行う必要がなくなります。


7
私は、組織的な目的でライブラリを常に書き換えています。
Maxpm

3
utilsパッケージが悪夢に変わった場合でも、すべてが悪いというわけではありません。どうすればそれを回避でき、そのためにコードが重複することはありません。したがって、テストの質が低下し、効率が低下します。
ニコール

2
@Renesis:utilsパッケージはgotoステートメントと同じくらい悲惨です。確かに、それ自体はそれほど悪いわけではありませんが、遅かれ早かれ、常に災害になります。コードの複製については、ほぼすべてのプロジェクトで同様のタスクを実行していることに気付いた場合、PythonやC#のようなものについては、おそらく他の人もそれを行っていて、それはおそらく標準ライブラリにあります。
whatsisname

6
私の経験では、独自のライブラリを持つエンジニアは、システムが提供するライブラリよりも先に使用することを好みます。そのため、個人のライブラリを持つことは良い習慣ではありません。私はかつて、彼の 'strlen'関数がコンパイラ提供の関数より高速であると絶対に確信していた男を書いたことがありました。strlenがいくつかのインライン化されたアセンブリ命令であり、他の人がもっとうまくやれるかもしれないと認めるには、彼がどのように簡単であるかを簡単に示しました。
JBRウィルキンソン

4
@JBRWilkinsonあなたのポイントはよく取られています。すべてのプログラマーが共通のコードを開発するのに適しているわけではありません。
ニコール

15

SmartFormat

私のお気に入りのユーティリティは私が書いたものです-正しい文法でデータを文字列に本当に簡単に変換できるシンプルな文字列ビルダ/フォーマッタです。

たとえば、ほとんどのプログラマーはテンプレートからテキストを作成します "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面白い!「条件付き」フォーマットの調査に長い時間を費やしましたが、今までに似たようなものは見つかりませんでした! MessageFormat持っているChoiceFormat驚くほど似た構文を可能にするクラスを!ドキュメントの例: "There {0,choice,0#are no files|1#is one file|1<are {0,number,integer} files}."。このリファレンスに言及してくれてありがとう。
スコットリッピー

@barjakただ私の主張を検証するために、SmartFormatにはさらに多くの機能があります!条件付き書式設定は、bool、date、timespan、objectなどの任意のデータ型に対して機能します。また、などの高度な演算子もサポートしてい"{Count:<0?negative|=5?five|>50&<100?large|other}"ます。これは、反射を持っている(すなわち"There are {items.Length} items"、配列項目とタイムスパンをフォーマットできPlusは、それがさらに多くの機能をサポートするためのプラグインモデルを持っている。
スコットRippey

確かに強力なようです。配列のフォーマットは興味深いものです。
バルジャック

@barjak:ええ、配列のフォーマットは本当に便利です!この例を確認してください。Smart.Format("There are {0.Count} files: {0:'{}'|, |, and }.", files);結果はになり"There are 3 files: 'a.txt', 'b.txt', and 'c.txt'."ます。それなしでは「ローカライズ」は想像できません。
スコットリッピー

7

K Combinator(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#tapRubyで呼び出されます)が救助します。

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

私はすでにC#(主に何らかの理由での代わりにList.Addreturn などのコレクションミューテーター)とScalaでそれを数回見逃しましたので、私はこれを持ち運びます:voidthis

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に欠けているものは、ID関数にアクセスするための適切な名前の付いた方法です。Haskellはid、Scala という名前で識別関数を提供しますidentity。これにより、次のようなコードを記述できます。

someCollection.groupBy(identity)

Rubyの同等のものは

some_collection.group_by {|x| x }

舌から正確に転がり落ちませんか?

修正は

IDENTITY = -> x { x }

some_collection.group_by(&IDENTITY)

ForEach(.NET)

C#のもう1つの非常に欠落しているメソッド:

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
あなたの最後の例は、計算された設計決定だったと思います。の概念は、ActionLINQの設計原則に反する副作用を意味します。
ChaosPandion

1
@ChaosPandion:これはLINQと何の関係がありますか?
ヨルグWミットタグ

@JörgW Mittag- IEnumerable拡張はLINQに追加されました。
ChaosPandion

2
@ChaosPandion:まだわかりません。ForEachLINQ演算子ではありません。LINQ演算子にのみ適用される制限がForEach、LINQ演算子ではないに適用されるのはなぜですか?そして、なぜ副作用は禁止されているIEnumerable.ForEachが許可されているのList.ForEachですか?また、なぜ副作用は禁止されてIEnumerable.ForEachforeachますが許可されていますか?
ヨルグWミットタグ

@JörgW Mittag-私が言っているのは、拡張機能に欠けているという事実は設計上の決定でした。をList<T>持つという事実は、ForEachそれが可変型であることを考えると合理的です。
ChaosPandion

6

Java Type Converterを持っています。公開署名があります

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

そして、ソース値を宛先タイプに変換するのが最善です。基本的に、静的に型付けされた言語内で動的型付けを行うことができます:-)

実際には、ボックス化された数値型で役立ちます。期待されるInteger場所に置くことができないのはどれほどイライラしますLongか?問題ありません、変換するだけです。または、関数がを予期しているがdoublenullそこに配置する必要がある場合はどうなりますか?NPEのKaboom。しかし、それを通過しconvert、あなたが得るNaN


興味深いソリューション。LongはIntegerを拡張すべきだといつも思っていました。しかし、それでもあなたはまだオートボクシングの問題を抱えているでしょう(私が知る限り、継承でオートボクシングが機能する方法はありません)。また、NaNサポートのために+1 。
ニコール

NaN素晴らしいです。整数にはそのようなものがないのは残念です。Integer.MIN_VALUE慣例として使用しました。通常、デフォルト値の0とは異なり、気付くのは「十分に奇妙」です。auto(un)boxingが(Double) nullとして扱わない理由はわかりませんNaN。それは明らかな正しい解決策です、私見。
ジョナスプラッカ

6

私が書いたその他のコードのうち、優れたもののほとんどは現在CCANにありますが、残りは既存のオープンソースプロジェクトのより良いバージョンを見つける傾向があります。最近では、汎用性の低い「その他」のコードを作成する機会が減り、そのようなコードのアプリケーション固有のバリアントを作成したり、自分でリリースできる汎用モジュールを作成したりしています。

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²)です。これは、そのタイプシグネチャにより、2つの要素が等しいかどうかをテストすることのみが許可されているためです。単純なO(n log n)の代替はですがmap head . group . sort、出力を生成する前に入力リスト全体を強制する必要がありますが、nubすぐに出力の生成を開始できます。以下は、nubaで既に表示されているアイテムを収集するO(n log n)の代替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のような厳密なモナドを使用している場合)。代替案は、サンクの塔を形成するのではなく、逆にリストを作成します。ベンチマークを通じて、少なくとも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。少し偏っていると思うかもしれませんが:)
ティムポスト

4

Perlを持たない言語でPerlの分割/結合を実装します。

また、考えているよりも何度もCでatoiとitoaを再実装しました(組み込みシステムのジャンク)。


4

いや

私はほとんどのコーディングをJavaで行います。ベストプラクティスは、Apache Commonsライブラリおよび類似のプロジェクトの「utils」を再利用することです。

あなたがそれについて客観的であるならば、あなた自身の「utils」コレクションが他の人々がすでにやったことの重要な改善になる少数のケースがあります。そして、それが改善されない場合、utilsライブラリはおそらく開発時間の浪費であり、将来のメンテナーにとっては迷惑/負担です。


3

Javaを使用して実行した日付操作がいくつかあり、それからJodaTimeの使用を開始しました。Java7に含まれることが良いことを聞いたので(まだそうなのかどうかはわかりませんが、そうでない場合でもそれを使用する価値があります。

約3つのチェーンされたメソッド呼び出しで、50以上の行クラスを1行に変えました。

好奇心のために、過去n週間の各日の日付を取得する必要がありました。たとえば、10週間前の月曜日の売上高など)。

そしてここにその一部があります

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

Javaには拡張メソッドがありますか?
クーゲル

いや、私はそれが、バージョン7でそれらを得るかもしれないと思う
NimChimpsky

2

utilsJavaであっても、常に何らかのパッケージを持っていますが、PHP utilsコレクションが最も再利用されています。Javaには非常に多くの優れたライブラリがあるため、プロジェクトに既にライブラリが含まれているか、不足しているいくつかのユーティリティを自分で設計する必要があります。PHPライブラリは、プロジェクトにそれらを含めたいと思うにはあまりにも多くの処理を行う傾向があります。

StackOverflowの助けを借りて洗練されたPHP用のこの関数が好きです...

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のBeanUtils for Javaに似ており、テンプレート言語のフォーム要素にソース配列のネストされた値を取得/設定できる単一のキーを与えて、同様の目的で使用します。

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

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

もちろん、PHPであるため、メソッドをできるだけ軽量に保ちたいので、BeanUtils ほど機能的ではありません。;)


2

Scala標準ライブラリには、最も一般的に使用される高階関数がいくつかありません。

私が最も頻繁に必要とする2つの機能:

// #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をやっていたときに1つ持っていましたが、Javaをやっているので、利用可能なすべての標準ライブラリとApacheプロジェクトから来るすべての利点を考慮すると、もはや意味がありません。

私のC libの便利な機能の1つは、2つの文字列と文字列の配列だけで有限状態マシンを定義できるquick&dirty有限状態マシン実装です。ルールに対して文字列をチェックするために使用できます(たとえば、「4..6文字の長さ、最初は1文字、残りの数字」)が、正規表現を使用できるため、まったく意味がありません。



1

私はdjangoで同じコードをたくさん書いていました、この共通のことをして、次にこの共通のこと、そして最後にその共通のことをしていました。基本的に、データベースから1つ以上のアイテムを取得するか、フォームの結果を保存します。

これらのことのそれぞれがビューで一度だけ発生する場合、django汎用ビューを使用できます。残念ながら、これらは実際には構成可能ではなく、いくつかのことを順番に行う必要がありました。

そこで、私はさらに一般的なビューライブラリを作成しました。まず、関連するクエリセット(またはその他)からアクションのリストを作成し、次にリストをビューにラップすることで機能します。

私はまだいくつかのビューを手書きで書かなければなりませんが、これらは通常は十分に複雑なので、再利用できるものはあまりありません。すべてのボイラープレートは、一般的なビューとして、またはビューデコレーター(多くの場合、装飾された一般的なビュー)として、他の場所に配置されます。いくつかの汎用ハンドラーは他のすべてを実行できるため、これは通常、私が記述するハンドラーの約10%になります。


1

はい。ただし、ドメイン固有のイディオム構造(ゲームオブジェクト固有のコンテナなど)に対してのみ。

複雑なものよりも単純なユーティリティツールなので、私はそこに何も誇りに思っていません。とにかく私は今のところ唯一のユーザーなので、誇りに思うことは何もありません。


1

STL sortおよびファンクターテンプレートに基づくC ++間接ソート。

間接的な並べ替えの必要性(目的の出力は、並べ替えられたデータ自体ではなく、データの並べ替えから生じる置換インデックスでした)は、多くのプロジェクトで何度も登場しました。私はいつも、STLがその実装を提供していない理由を不思議に思っていました。

もう1つは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
c'mon

2
さあ、それは問題ではありません。
ジョシュK

1
-2であなたの現在の投票で、私はそれは本当に問題で...ありません推測している
user7676

8
盗作は、明らかな場合を除き、最高のお世辞です。
Maxpm

5
ダウンボットボタンには「この答えは役に立たない」と書かれています。「...しかし確か面白いです」:私はaditionalボタンの必要があると思います
skajfesは
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.