Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

Regex za redove sa ciframa i LINQ za LUHN

[es] :: .NET :: Regex za redove sa ciframa i LINQ za LUHN

[ Pregleda: 2314 | Odgovora: 16 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6042



+4631 Profil

icon Regex za redove sa ciframa i LINQ za LUHN08.01.2010. u 17:32 - pre 174 meseci
Imam mali brain-freeze ili od sume ne vidim drvo.

Dakle imam multiline tekst i treba da uradim capture redova u kojima se nalazi 10 i vise cifara, ali ne izcela nego ukupno u redu

npr:

prvi red nema cifre
ovaj 2. red ima tacno 2 cifre
1234 e vode vec ima 5 cifara
1.2-3+4/5 e ovaj red mora da bude uhvacen 6-7=8-9-0


koji regex hvata ovo?

Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
 
Odgovor na temu

Igor Gajic

Član broj: 93194
Poruke: 747
93.86.87.*



+987 Profil

icon Re: Regex za redove sa ciframa i LINQ za LUHN08.01.2010. u 18:28 - pre 174 meseci
Ako ne mora RegEx moze i ovako:

Code:

line.ToCharArray().ToList().Where(s => s >= '0' && s <= '9').Count();


EDIT:

RegEx

Code:

Regex regex = new Regex("([0-9].*){10,}", RegexOptions.Compiled);


Prvi nacin je 15+ puta brzi....

[Ovu poruku je menjao Igor Gajic dana 08.01.2010. u 19:51 GMT+1]
 
Odgovor na temu

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6042



+4631 Profil

icon Re: Regex za redove sa ciframa i LINQ za LUHN10.01.2010. u 19:42 - pre 173 meseci
A nismo se dobro razumeli, trebalo mi je da u regex ubacim ceo tekst odjednom i da dobijem capture grupu sa svim linijama koje zadovoljavaju uslov. Inace sam nasao resenje posle prespavane noci :)

Code:
^(?<linija>.*(\d.*){10})$


uz multiline flag.




Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
 
Odgovor na temu

Shadowed
Vojvodina

Član broj: 649
Poruke: 12851



+4784 Profil

icon Re: Regex za redove sa ciframa i LINQ za LUHN10.01.2010. u 21:10 - pre 173 meseci
Umm, ako je onaj prvi nacin brzi, zar ne mozes samo da uradis String.Split() pa nadovezes ono dato? Ili bas mora regex? :)
 
Odgovor na temu

Igor Gajic

Član broj: 93194
Poruke: 747
93.86.87.*



+987 Profil

icon Re: Regex za redove sa ciframa i LINQ za LUHN10.01.2010. u 21:41 - pre 173 meseci
Pa i meni Regex deluje kao overkill.

Inace ovo se trivijalno moze resiti i kao:


Code:

List<string> linije = new List<string>();
foreach (string line in text.Split())
{
   int brojCifara = 0;

  for (int i = 0; i < line.Length; i++)
     if (line[i] >= '0' && line[i] <= '9') brojCifara++;

   if(brojCifara >=10) linije.Add(line);
}
 
Odgovor na temu

Shadowed
Vojvodina

Član broj: 649
Poruke: 12851



+4784 Profil

icon Re: Regex za redove sa ciframa i LINQ za LUHN10.01.2010. u 21:55 - pre 173 meseci
Pa, ono sto si prvo dao radi manje/vise to unutar foreach-a. Jedino sto sto tamo nisi selektovao.
Bilo bi ovako nesto:

Code:
from str in podatak.Split("\n")
where str.ToCharArray().ToList().Where(s => s >= '0' && s <= '9').Count() >= 10
select str


Prelomih da bude citljivije.
Linq rocks :)
 
Odgovor na temu

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6042



+4631 Profil

icon Re: Regex za redove sa ciframa i LINQ za LUHN10.01.2010. u 22:05 - pre 173 meseci
Problem jeste trivijalan, da je samo .NET ne bih pitao potreban mi je regex jer sinhronizujem vise sistema, .NET je samo jedan.
U osnovi imaju gomile tekstova koje moraju da audituju dok prolaze "checkpointe" a audit filteri su mi regexi.
I regex resenje je prosto samo mi mozak stao u tom trenutku

I da, Linq rocks Pokazah ti Luhn validator kao one liner u Linqu

Code:
string cardNumber = "5424000000000016"; // test
bool valid = cardNumber.ToList().ConvertAll(c => int.Parse(c.ToString())).AsEnumerable().
     Reverse().Aggregate(new {f = true, s = 0}, (o, i) => new {f = !o.f, s = o.s + (o.f ? i : (i*2)%9)}).s % 10 == 0;






Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
 
Odgovor na temu

Igor Gajic

Član broj: 93194
Poruke: 747
93.86.87.*



+987 Profil

icon Re: Regex za redove sa ciframa i LINQ za LUHN10.01.2010. u 22:16 - pre 173 meseci
Jeste isto kao i LINQ ali opet ostaje pitanje brzine, taj dodatak apstrakcije i konvertovanje u niz pa u listu oduzima vreme, pa je bare-metal resenje najbrze, ali LINQ je opet najcitkiji... Sve je pitanje kompromisa...
 
Odgovor na temu

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6042



+4631 Profil

icon Re: Regex za redove sa ciframa i LINQ za LUHN10.01.2010. u 22:32 - pre 173 meseci
U pravu si, mada i sebe sve redje hvatam da jurim bare metal resenje za vecinu stvari. AKo pogledas i svoj primer i ti koristis Split() sto je u osnovi apstrakcija kao sto je foreach (koji ide kroz IEnumerable) gde bi najbrze resenje bilo skeniranje svih karaktera uz brojace i reset posle svakog \n.

Ono sto mene najvise zulja u LINQu je sto nema dovoljno ekstenzija nad "rinfuznim" tipovima sto forsira nepotrebne konverzije u druge rinfuzne tipove koji ih imaju, minimum bi IEnumeraable morao da ima sve ekstenzije i da ga svi rinfuzni tipovi publikuju, ne postoji npr nijedan dobar razlog da string ne daje IEnumerable<char> koji bi direktno cupao karaktere iz stringa bez string operacija. I ovaj moj luhn primer bi bio kraci i brzi da ne mora da se konvertuje u list, a btw shadowed mislim da tvoj linq kod moze krace; nemam VS sada ali bi trebalo da array ima where ekstenziju. Sem tih konverzija ako pogledas kako su linq operacije implementirane videces da i nemas mnogo manevarskog prostora do bare metal resenja, samo vise koda.
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
 
Odgovor na temu

Igor Gajic

Član broj: 93194
Poruke: 747
93.86.87.*



+987 Profil

icon Re: Regex za redove sa ciframa i LINQ za LUHN10.01.2010. u 23:11 - pre 173 meseci
BTW:

Luhn validation, 2. nacin

Code:

            bool valid = 
                cardNumber
                .ToList()
                .Select(s => s-48)
                .Reverse()
                .Select((s,i)=> i%2 == 1 ? ((s*2)%9 == 0 ? 9 : (s*2)%9) : s)
                .Aggregate((x, s) => x + s) % 10 == 0;



LINQ je dusu dao za logicko razmisljanje i nalazenje alternativnih resenja...
 
Odgovor na temu

Shadowed
Vojvodina

Član broj: 649
Poruke: 12851



+4784 Profil

icon Re: Regex za redove sa ciframa i LINQ za LUHN11.01.2010. u 00:12 - pre 173 meseci
Citat:
mmix: btw shadowed mislim da tvoj linq kod moze krace; nemam VS sada ali bi trebalo da array ima where ekstenziju.

Ja sam samo kopirao ono iz prve poruke :)
Ima Where ekstenziju.

Slazem se oko String-a. Zaista bi mogao malo vise.. da lici na List<Char> ili nesto slicno.
 
Odgovor na temu

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6042



+4631 Profil

icon Re: Regex za redove sa ciframa i LINQ za LUHN11.01.2010. u 13:12 - pre 173 meseci
Svidja mi se ova fora sa select transformacijom, trazio sam nacin da dodjem do indeksa, nisam ni pomislio da select to daje. cool.

isti imam bug u mom LINQu sa 9-om na parnoj poziciji, i isto sam konacno nasao IEnumerabe<char> u stringu Nije uopste preko metoda vec sam string publikuje IEnumerable (d'oh). Ovo resenje dakle moze da se jos malo optimizuje i skrati:

- ne mora da se konvertuje u List<char>
- taj aggregate na kraju je u stvari prosti Sum
- u selct transformaciji moze da se smanji broj matematickih operacija, dovoljno je da se proveri >4 i da se koristi -9 umesto %9 nije neki benefit al ako vec jurimo "savrsenstvo"

Code:

            bool valid = cardNumber
                             .Select(c => c - 48)
                             .Reverse()
                             .Select((s, i) => i%2 == 1 ? (s > 4 ? s*2 - 9 : s*2) : s)
                             .Sum()%10 == 0;


inace, ovaj metod ne proizvodi ni jednu temp kopiju podataka, suma na kraju iterira kroz tri razlicita iteratora u jednom cugu nad stringom Apstraktno ili ne, mislim da je sasvim komparativno sa bare metal resenjem.

A inace, pricasmo io regexu
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
 
Odgovor na temu

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6042



+4631 Profil

icon Re: Regex za redove sa ciframa i LINQ za LUHN11.01.2010. u 14:37 - pre 173 meseci
Evo ga jos jedan, malo drugacija kombinacija transformacija, kad vec prolazi samo jednom treba to iskoristiti. Trebalo bi videti koji je brzi

Code:
           bool valid = cardNumber
                             .Reverse()
                             .Select((c, i) => (c - 48) << (i & 1))
                             .Select(s => s > 9 ? s - 9 : s)
                             .Sum()%10 == 0;

Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
 
Odgovor na temu

Igor Gajic

Član broj: 93194
Poruke: 747
*.static.sbb.rs.



+987 Profil

icon Re: Regex za redove sa ciframa i LINQ za LUHN11.01.2010. u 15:39 - pre 173 meseci
Odlicno resenje

A krenuli smo od kobajle od LINQ-a...
 
Odgovor na temu

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6042



+4631 Profil

icon Re: Regex za redove sa ciframa i LINQ za LUHN11.01.2010. u 18:11 - pre 173 meseci
ma meni samo zao sto select u query languagu nema varijantu koja eksponira index niti ima direktne agregacije, al bilo bi cool da sve ovo moze u "from d in cardnumber...."
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
 
Odgovor na temu

Igor Gajic

Član broj: 93194
Poruke: 747
93.86.87.*



+987 Profil

icon Re: Regex za redove sa ciframa i LINQ za LUHN11.01.2010. u 19:32 - pre 173 meseci
LUHN LINQ testirano na 1e+6 16-bajtnih stringova:

originalno resenje: 5.61s
moje resenje: 2.59s
poslednje resenje: 1.91s

EDIT:

Bare-metal resenje se izvrsava za 0.016s (!)

Code:

                int sum = 0;
                for (int i = 16; i < 0; i--)
                {
                    int current = (cardNumber[i] - 48) << (i & 1);
                    if(current > 9) current -=9;
                    sum += current;
                }
                bool valid = sum % 10 == 0;


[Ovu poruku je menjao Igor Gajic dana 11.01.2010. u 20:47 GMT+1]
 
Odgovor na temu

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6042



+4631 Profil

icon Re: Regex za redove sa ciframa i LINQ za LUHN11.01.2010. u 21:18 - pre 173 meseci
Imas pretpostavku da je card number 16 karaktera (sto btw ni u praksi ne mora biti tacno, amex ima 15 i luhn validiran je). Probaj sa cardNumber.length sa tim sto bi morao da promenis i&1 formulu jer moze da krene i od neparne pozicije. Mada ne verujem da ce to uticati mnogo na rezultat, ma koliko optimizovali query ipak su operacije enumeratora ustvari yield metode sa svim overhaedom istih, ne verujem da bi bilo koje LINQ resenje bilo brze.


U stvari bliza komparacija bi bila naspram foreach verzije.
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
 
Odgovor na temu

[es] :: .NET :: Regex za redove sa ciframa i LINQ za LUHN

[ Pregleda: 2314 | Odgovora: 16 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.