Kendi 'misc utils' kitaplığınız var mı? En çok hangi bölümden gurur duyuyorsun? [kapalı]


32

Çoğumuzun sık kullandığımız araç ve gereçlerle kendi kişisel kütüphanemizi koruduğumuzu biliyorum.

Benim 16 yaşımdan beri benimki oldum, bu yüzden oldukça büyük bir boyuta ulaştı. Yazdığım bazı şeyler o zamandan beri çerçeveye eklendi. LINQ'dan çok önce genetik algoritmalarla kullanılmak üzere kendi küçük ifade ağaçlarını kendim yazdım, o zamanlar çok hoşuma gitti ve ondan gurur duydum - elbette şimdi oldukça işe yaramaz. Ancak son zamanlarda bunu gözden geçiriyorum ve .NET 4.0'a geçiyorum ve ilgimi çekti.

Bu yüzden kütüphanenizi ne için kullandığınızı merak ediyorum. Belki yararlı küçük pasajlar için harika fikirler bulabilir ve bunları kendi aramızda paylaşabiliriz.

Yani benim sorularım:

  • Çeşitli bir yardımcı program kütüphaneniz var mı?
  • En çok hangi bölümden gurur duyuyorsun ve neden?

İsterseniz bir kod örneği verin :-)


Kimse cevapları yumuşatıyor gibi görünmüyor ...
Joey Adams 20:

@Joey Adams Doğru mu? Şu anda 17 soru oy ve 6 toplam cevap oy.
Nicole,

Gerçekten değer kazandıracak cevaplar göremiyorum. Bir galibiyetin onlar için anlamı nedir? Sorunun doğası öyledir ki cevaplar sadece "ah. Güzel" olur. Bir çeşit tepki, ve sonra ya her şeyden fazla ya da hiç bir şeyden fazla olmaz. (Ve her cevabı kırmaktan hoşlanmıyorum, çünkü orada var. Başka bir şey yoksa, oy kullanmam.: P)
Adam Lear

@Anna Lear, tamam, mazeretin yok :)
Nicole

3
Uygun bir yardımcı program github'a konulmalı ve dünya ile paylaşılmalıdır. Eğer gerçekten iyiyse, saklı tutulması bir anlam ifade etmiyor.
İş

Yanıtlar:


27

Yok hayır.

Bir düzine geliştiricinin projelere kendi küçük "util.h" stil kütüphanelerini ekleyen bazı kabus etkilerini gördüm ve tutarsız işlev isimlendirme ve davranışlarının devasa bir karmaşasına dönüşmesini sağladım. PHP'ye çok benzer. Bu yüzden bunu yapmaktan kaçınıyorum.

Bana C # ve python gibi mümkün olduğunda önümde ihtiyaç duyduğum hemen hemen tüm araçları ve kütüphaneleri veren programlama ortamları kullanarak bunu yapmaktan kaçınıyorum.


7
Kütüphanemi organizasyon amaçları için sürekli yeniden yazıyorum.
Saat

3
Utils paketinin kabusa dönüştüğü durumlar, hepsinin kötü olduğu anlamına gelmez. Bundan nasıl kaçınabileceğinizi ve bundan dolayı daha fazla kod çoğaltmaya sahip olmadığınızı göremiyorum. Ve bu nedenle, daha kötü test ve daha az verimlilik.
Nicole,

2
@Renesis: utils paketleri goto ifadeleri kadar fecidir. Tabii, kendi başına o kadar da kötü değil, ama görünüşte her zaman er ya da geç bir felaket olur. Kod çoğaltmaya gelince, kendinizi neredeyse tüm projelerinizde benzer bir iş yaparken bulursanız, o zaman python veya C # gibi bir şey için, diğer insanlar da muhtemelen bunu yapıyor ve muhtemelen o zamana kadar standart kütüphanelerde.
whatsisname,

6
Tecrübelerime göre, kendi kütüphaneleri olan mühendisler, onu sistem tarafından sağlananlardan önce kullanmayı tercih edeceklerdir, bu nedenle kişisel kütüphanelere sahip olmak iyi bir uygulama değildir. Bir zamanlar, 'strlen' işlevinin derleyici tarafından sağlanandan daha hızlı olduğuna kesinlikle ikna olmuş bir adamım vardı , çünkü yazmıştı . Belki de diğer insanların daha iyisini yapabileceğini kabul etmesi için ne kadar gergin kaldığının basit bir gösterimini yaptı.
JBRWilkinson

4
@JBRWilkinson Amacınız iyi karşılandı. Her programcı ortak kod geliştirmeye uygun değildir.
Nicole,

15

SmartFormat

En sevdiğim yardımcı program yazdığım programdır - veriyi doğru gramer ile dizgelere dönüştürmeyi gerçekten kolaylaştıran basit bir string kurucu / biçimlendirici.

: Örneğin, çoğu programcı bir şablondan metin oluşturmak "There are {0} items remaining" ama gramer hataları bu yol: "There are 1 items remaining".

Yani, SmartFormat yazdığınız sağlar: "There {0:is|are} {0} item{0:|s} remaining".

Siz sadece String.Format(...)bununla değiştirin Smart.Format(...)ve o kadar!

SmartFormat kodu açık kaynak: http://github.com/scottrippey/SmartFormat/wiki


Bu bana kullanılan formatı hatırlatıyor java.text.MessageFormat.
Aralık'ta

@barjak İlginç! "Koşullu" formatlamayı araştırmak için çok zaman harcadım ve şimdiye kadar hiçbir zaman benzer bir şey bulamadım! MessageFormatsahip ChoiceFormatbir ŞAŞIRTICI DERECEDE benzer bir sözdizimi verir sınıfı! Belgeleri bir örnek: "There {0,choice,0#are no files|1#is one file|1<are {0,number,integer} files}.". Bu referansı belirttiğiniz için teşekkür ederiz.
Scott Rippey,

@barjak Sadece amacımı doğrulamak için, SmartFormat'ın daha birçok özelliği var! Koşullu biçimlendirme, bool, date, timespan ve object gibi herhangi bir veri türü için çalışır; Aynı zamanda gibi gelişmiş operatörleri de destekler "{Count:<0?negative|=5?five|>50&<100?large|other}". Yansıması vardır (yani "There are {items.Length} items", dizi öğelerini ve zaman
aralıklarını

Gerçekten de güçlü görünüyor. Diziler biçimlendiriliyor.
barjak

@ barjak: Evet, dizi biçimlendirme gerçekten yararlıdır! Şu örneği inceleyin: Smart.Format("There are {0.Count} files: {0:'{}'|, |, and }.", files);sonuçlanır "There are 3 files: 'a.txt', 'b.txt', and 'c.txt'.". Onsuz yerelleşmeyi hayal bile edemiyorum.
Scott Rippey

7

K Birleştirici (C #, Scala)

K birleştiricisini Ruby'de oldukça sık, çoğunlukla katlama işleminin bu örnekte olduğu gibi bir geri dönüş değeri yerine bir yan efektle gerçekleştirildiğinde katlamalarda kullanıyorum:

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

Bu, her bir elemanın ne sıklıkta gerçekleştiğini sayar some_collection. Ne yazık ki, aslında işe yaramaz, çünkü blok her tekrarlamada akünün yeni değerini döndürmek zorundadır, ancak Ruby atamalarında atanan değere göre değerlendirilir.

Dolayısıyla, akümülatörün yeni değerini açık bir şekilde bu şekilde döndürmeniz gerekir:

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

Ancak bu tür açık dizilimleri, bu işlevsel-ish stilinde, kıvrımları kullanarak çirkin buluyorum. K birleşimi ( Object#tapRuby'de denir ) kurtarmaya:

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

C # 'da birkaç kez çok fazla özledim (çoğunlukla bazı nedenlerden dolayı List.Addgeri dönüş gibi mutasyonlar voidnedeniyle this) ve Scala, bu yüzden bunu yapıyorum:

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;
        }
    }
}

ve Scala'da:

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) }

Kimlik İşlevi (Yakut)

Ruby'de kaçırdığım bir şey, kimlik işlevine erişmek için güzel bir şekilde adlandırılmış bir yoldur. Haskell isminin idaltında Scala ismini, ismin altında Scala ismini verir identity. Bu, birinin şöyle bir kod yazmasını sağlar:

someCollection.groupBy(identity)

Ruby'deki karşılığı

some_collection.group_by {|x| x }

Dilden tam olarak çıkmıyor, değil mi?

Düzeltme

IDENTITY = -> x { x }

some_collection.group_by(&IDENTITY)

ForEach (.NET)

C # başka bir çok sık eksik yöntem:

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
Son örneğinizin hesaplanmış bir tasarım kararı olduğunu düşünüyorum. Bir kavramı ActionLINQ tasarım ilkelerine aykırı yan etkileri ima eder.
ChaosPandion

1
@ChaosPandion: Bunun LINQ ile ne ilgisi var?
Jörg W Mittag

@ Jörg W Mittag - IEnumerableLINQ için uzantılar eklendi.
ChaosPandion

2
@ ChaosPandion: Hala anlamıyorum. ForEachLINQ operatörü değil. ForEachBir LINQ operatörü olmayan, yalnızca LINQ operatörleri için geçerli olan kısıtlamalar neden uygulanmalıdır ? Ve neden yan etkiler yasak IEnumerable.ForEachama neden yasak List.ForEach? Ayrıca, neden yan etkiler yasak IEnumerable.ForEachancak bunun için yasak foreach?
Jörg W Mittag

@ Jörg W Mittag - Söylediğim şey, uzantılardan eksik olduğu gerçeği bir tasarım kararıydı. Değişmeli bir tür olduğu düşünüldüğünde makul List<T>bir gerçeği vardır ForEach.
ChaosPandion

6

Java tip dönüştürücüm var. Halka açık bir imzası var.

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

ve kaynak değeri hedef türüne dönüştürmek için elinden gelenin en iyisini yapar. Aslında statik olarak yazılmış bir dilde dinamik yazma yapmanızı sağlar :-)

Kutulu sayısal türlerde aslında yararlıdır. Beklenen Integeryere bir yere koyamamak ne kadar rahatsız edici Long? Sorun değil, sadece dönüştürün. Ya da fonksiyonunuz a bekliyorsa double, ama nulloraya koymak zorundaysanız ? Kaboom, bir NPE. Ama içine koy convertve sen anlarsın NaN.


İlginç bir çözüm. Her zaman Long'un Tamsayıyı genişletmesi gerektiğini düşündüm. Fakat o zaman bile, hala otomatik kutulama sorunu yaşarsınız (bildiğim kadarıyla otomatik kutulamanın kalıtımla çalışmasına imkân yoktur). Ayrıca, NaNdestek için +1 .
Nicole,

NaNmükemmel. Tamsayılar için böyle bir şey olmaması çok kötü. Integer.MIN_VALUEKongre olarak kullandım . Bu oto (me) boks tedavi etmez neden bilmiyorum varsayılan değer 0. aksine genellikle "tuhaf yeterli" fark edilmek var (Double) nullolarak NaN. Bu bariz doğru çözüm, IMHO.
Joonas Pulakka,

6

Yazdığım yanlış koddan, şu anda iyi olanların çoğu CCAN'da , geri kalanı ise mevcut açık kaynaklı projelerde daha iyi sürümler bulma eğilimindeydi. Bugünlerde daha az genel amaçlı "misc" kodu yazdığımı, bu kodun uygulamaya özel varyantlarını veya kendi başıma serbest bırakabileceğim genel amaçlı modülleri yazdığımı düşünüyorum.

C

İşte birden fazla kullandığım bir fonksiyon ve typedef. Zamanlamaya ihtiyaç duyan uygulamalar için basitlik açısından milisaniyeleri yenmek zordur:

#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;
}

Ve tekrar tekrar kullanmaya meyilli olduğum daha çeşitli C fonksiyonları:

/* 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

Haskell'in nub :: (Eq a) => [a] -> [a]işlevi O (n²) 'dir, çünkü türünün imzasına göre, yalnızca iki öğenin eşit olup olmadığını sınamaya izin verilir. Basit bir O (n log n) alternatifidir map head . group . sort, ancak çıktı üretmeden önce tüm girdi listesinin zorlanmasını gerektirir, oysa nubçıktı üretmeye hemen başlayabilir. Aşağıdakiler, daha nubönce görülmemiş öğeleri bir toplayana bir O (n log n) alternatifidir 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, ben alternatifler kullanmak sequence, mapM, forM, replicateM, ve filterM. Bu eylemlerin her biri bir liste oluşturur, ancak liste bütünüyle tamamlanıncaya kadar liste kullanılamaz (IO gibi katı bir monad kullanıyorsanız). Alternatifler, en azından GHC ile kıyaslamada daha hızlı bulduklarını bulduğum bir kuleler kulesi oluşturmak yerine listeyi tersten oluşturuyor.

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')

Not: sequence_, mapM_, forM_, ve replicateM_sonuç listesinde ilgilenen değilse fonksiyonlar hala daha iyi bir seçimdir.


Önyargılı olarak değerlendirilebilsem de, CCAN için +1 :)
Tim Post

4

Buna sahip olmayan dillerde split / join ala Perl uygulayarak kurdum.

Ayrıca, atoi ve itoa'yı C'ye düşündüğümden daha fazla uygulamıştım (gömülü sistemler önemsiz).


4

Yok hayır.

Kodlamamın çoğunu Java'da yapıyorum ve en iyi uygulama Apache Commons kütüphanelerinden ve benzer projelerden "utils" kullanmaktır.

Bu konuda objektif iseniz, kendi "utils" koleksiyonunuzun başkalarının zaten yaptıklarını önemli ölçüde iyileştireceği birkaç durum var. Ve eğer bir gelişme değilse, utils kütüphaneniz büyük olasılıkla bir geliştirme zamanı kaybı ve gelecekteki bakımcılar için sıkıntı / yük demektir.


3

Java kullanarak yaptığım bazı tarih manipülasyonları yaptım, sonra JodaTime'ı kullanmaya başladım, çünkü bu konuda iyi şeyler duydum ve Java 7'ye dahil edilmeye başladım (hala böyle olup olmadığından emin değilim, ama hala olmasa bile onu kullanmaya değmez).

50'den fazla çizgi sınıfını üç zincirleme yöntem çağrısı ile tek bir satıra dönüştürdü.

Meraklı için, n haftanın her günü için tarih almakla ilgiliydi : örneğin, 10 hafta önce bir pazartesi için satış rakamı vs.).

Ve işte bunun bir parçası

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

Java uzatma yöntemleri var mı?
Kugel,

hayır, ama onları sürüm 7'de alıyor olabileceğini düşünüyorum
NimChimpsky

2

utilsJava'da bile her zaman bir çeşit paketim var ama PHP utils koleksiyonum en çok kullanılanı. Java'da o kadar çok iyi kütüphane var ki, ya zaten projeye dahil edilmiş bir kütüphanem var ya da kendi başıma eksik olan birkaç yardımcı programı tasarlamam gerekiyor. PHP kütüphaneleri, projelerime dahil etmek istemem için çok fazla şey yapma eğilimindedir.

PHP için bu işlevi sevdim , StackOverflow'un yardımıyla rafine edilmiş ...

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'nin Java için BeanUtils'ine benziyor ve benzer bir amaçla kullanıyorum, bir şablon dilindeki form elemanlarına kaynak dizide iç içe bir değer alabilen / ayarlayabilen tek bir anahtar:

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

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

Öyle olmadığını Tabii, PHP olmak, mümkün olduğunca hafif olarak yöntemini tutmak istedim oldukça BeanUtils kadar featureful;)


2

Scala standart kütüphanesinde en sık kullanılan bazı üst düzey işlevler yoktur.

En çok ihtiyaç duyduğum iki işlev:

// #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

Şu anda hayır. C yaparken bir tane vardı, ama şimdi Java yapıyorum, tüm standart lib'ler ve Apache projesinden gelen tüm güzellikler göz önüne alındığında artık mantıklı değil.

C lib'ümdeki faydalı şeylerden biri, yalnızca iki dizili ve bir dizi dizili bir sonlu durum makinesinin tanımlanmasına izin veren hızlı ve kirli sonlu durumlu bir makine uygulamasıydı. Dizeleri kurallara göre kontrol etmek için kullanılabilir (örneğin, "4..6 karakter uzunluğunda, ilk önce bir harf, kalan rakamlar" olmalıdır), ancak regex'lerin mevcudiyeti o şeyi tamamen anlamsız kılmıştır.



1

Django'da aynı kodun çoğunu yazıyordum, Bu ortak şeyi yap, sonra bu ortak şeyi ve sonunda bu ortak şeyi. Temel olarak veritabanından bir veya daha fazla öğe alın veya bir formun sonuçlarını kaydedin.

Bu şeylerin her biri görünümde yalnızca bir kez meydana gelirse, o zaman django genel görünümlerini kullanabilirim. Ne yazık ki, bunlar gerçekten bir araya getirilemiyor ve sırayla birkaç şey yapmam gerekiyordu.

Bu yüzden, önce ilgili sorgulayıcılardan (veya her neyse) bir eylemler listesi oluşturarak çalıştığım ve daha sonra listeyi bir görünüme sardığı bir daha genel görüş kütüphanesi yazdım ve yazdım.

Hala elimden bazı görüşler yazmam gerekiyor, ancak bunlar genellikle içlerinde yeniden kullanılabilecek pek bir şey olmadığı kadar karmaşık. Kazan plakasının tamamı başka bir yere, genel bir görünüme veya bir görünüm dekoratörüne (genellikle dekore edilmiş bir genel görünüm) düşer. Bu genellikle, yazdığım işleyicilerin yaklaşık% 10'udur, çünkü bazı genel işleyiciler diğer her şeyi yapabilir.


1

Evet, ancak yalnızca etki alanına özgü deyimler yapıları (oyun nesnelerine özgü kapsayıcılar gibi) için.

Her şeyden daha basit bir yardımcı araç olduğundan, oradaki hiçbir şeyden gurur duymuyorum. Zaten şu an eşsiz kullanıcıyım, bu yüzden gurur duyulacak hiçbir şey yok.


1

C ++ dolaylı sıralama, STL sortve bir functor şablonunu temel alır.

Dolaylı sıralama gereksinimi (istenen çıktının, verilerin sıralanmasından kaynaklanacak ama sıralanan verilerin kendisi değil) permütasyon endeksleri olduğu bir çok projede birçok kez ortaya çıktı. STL'nin neden bunun için bir uygulama sağlamadığını hep merak etmişimdir.

Bir diğeri, pozitif ve negatif indekslerin vektör boyutuyla modülo olduğu bir C ++ döngüsel vektörüdür (böylece herhangi bir tamsayı değerleri vektör için geçerli indeksler).


-4

Bilgisayarımda Java geliştirme yaparken küçük bir yardımcı yazılım paketi yazdım. Lisede fen bilgisi dersi. En çok rastgele sayı üretecimle gurur duyuyorum.

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

Benim ilham kaynağı.


12
Hadi, xkcd ....
Darknight

2
Hadi, önemli değil.
Josh K

1
Şu anki -2
oyunuzla

8
İntihal, açık olduğu durumlar hariç, en yüksek suçluluk şeklidir.
Saat

5
Olumsuz oy düğmesi: "Bu cevap kullanışlı değil" diyor. Sanırım
kısmi
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.