Pieniä kysymyksiä ohjelmoinnista

Liittynyt
15.10.2021
Viestejä
17
Pieniä pulmia koulun tehtävien kanssa (koulun kalvoista ei mitään apua), eli pitäs tehdä tämmöinen tehtävä:
Create a program which is able to calculate and output (as double value, with 3 decimals) the
average value of the integer numbers given by the user. New numbers are asked until the user
enters a negative value, for example -1.
Yritin tuonne (vanhan tehtävän pohjalle jossa laskettiin syötettyjen lukujen neliöt) pohjalle tehdä tuota uudempaa tehtävää mutta en saa toimimaan tuonne while loopissa sitä että lasketaan keskiarvo ja sitä mukaa kun käyttäjä lisää numeroita keskiarvo muuttuu. Eli loopissa täytyy säilyttää arvot ja ne päivittyy sitä mukaa kun käyttäjä lisää numeroita.
Console.WriteLine("Give the first number to calculate average from or skip the whole thing by entering -1");
int n = Convert.ToInt32(Console.ReadLine());
while(n >= 0)
{
Console.WriteLine(n*n);
Console.WriteLine("Give a new number to calculate a square from or end with -1");
n = Convert.ToInt32(Console.ReadLine());
}

Tuo siis on se aiempi tehtävä esimerkkinä
Hei! Tuossa tehtävässä taitaa olla tarkoitus tutustua listoihin. Luo tyhjä lista loopin ulkopuolella ja täytä sitä loopin sisällä sitä mukaa kun käyttäjä antaa arvoja. Keskiarvolle taitaa löytyä suoraan valmis metodi listatyypistä.
 
Liittynyt
21.10.2016
Viestejä
9 054
Tai sit vaa muuttujat syotteidenMaara ja summa, joita päivitetään joka syötteen jälkeen ja niistä saadaan laskettua ka.?

Edit: jos listat ei oo vielä tuttuja
 
Liittynyt
07.01.2021
Viestejä
678
Sinun pitää määritellä kaksi uutta muuttujaa: summa ja laskuri joka kertoo montako arvoa on jo annettu. Alusta molemmat nollaksi ja kasvata arvoja kun käyttäjä antaa muun arvon kuin -1.

Tuo convert-funktio on varmaan väärä, kuulostaa että tuo muuntaa kokonaisluvuksi?

E. Listallakin tuon saa toki tehtyä ja pitää käyttää jos tehtävänanto niin käskee. Mutta annetun tehtävän perusteella tarpeetonta.
 
Liittynyt
21.10.2016
Viestejä
9 054
Sinun pitää määritellä kaksi uutta muuttujaa: summa ja laskuri joka kertoo montako arvoa on jo annettu. Alusta molemmat nollaksi ja kasvata arvoja kun käyttäjä antaa muun arvon kuin -1.

Tuo convert-funktio on varmaan väärä, kuulostaa että tuo muuntaa kokonaisluvuksi?

E. Listallakin tuon saa toki tehtyä ja pitää käyttää jos tehtävänanto niin käskee. Mutta annetun tehtävän perusteella tarpeetonta.
Jep, tehtävässä haetaan ihan perus ohjelmointilogiikkaa kielestä välittämättä.
 
Liittynyt
23.12.2016
Viestejä
651
Siis onko tämä soveltuva tuohon keskiarvoon:

if(Int32.TryParse(Console.ReadLine(), out input))
{
numbers = input;
sum += numbers;
average += ((decimal)input - average) / (i + 1);
}
 
Liittynyt
16.11.2020
Viestejä
2 565
Siis onko tämä soveltuva tuohon keskiarvoon:

if(Int32.TryParse(Console.ReadLine(), out input))
{
numbers = input;
sum += numbers;
average += ((decimal)input - average) / (i + 1);
}
Niin siis kannattaa varmaan vaan kasvattaa a) laskuria, jossa on kerättyjen lukujen määrä ja b) summaa, jossa on kerätyt luvut yhteenlaskettuna. Sen jälkeen keskiarvo on vaan summa / maara, joka lasketaan sen jälkeen, kun on huomattu, että käyttäjä on syöttänyt -1.

Jos tää siis liittyy tuohon enkun kieliseen tehtävänantoon.

Laskuri ei tarvii mitään tyyppimuunnoksia, kunhan sen alustaa kokonaisluvuksi ennen lukuja kysyvää luuppia, mutta käyttäjältä saatu syöte pitää muuntaa merkkijonosta luvuksi. Joku String -> Integer muunnostemppu löytyy varmaan tuostakin kielestä, jolla peuhataan. Ja summaa siis kasvatetaan kokonaislukuna.

Keskiarvo (eli tuon em. jakolaskun tulos) pitää esitellä desimaaliluvuksi ja lopulliselle tulokselle pitää vielä kertoa desimaaliformaatti, joka oli kolmen desimaalin tarkkuudella. Jos tuo on jotain C#:a, niin varmaan joku linkin temppu toimii.
 
Liittynyt
16.11.2020
Viestejä
2 565
No juu, tarvinnee olla muotoa (java-syntaksilla) double avg = sum * 1.0 / count, jos sum ja count on määritelty kokonaisluvuiksi.

Saa varmaan tehdä jotenkin muutenkin, mutta minä esittelisin varmaan luonnostaan sekä summan että laskurin kokonaislukuina, kun sellaisia ne ovat.
 
Liittynyt
17.10.2016
Viestejä
5 658
Miten 1.124 + 4.238 on kokonaisluku?
Nuo on laittomia inputteja ko. ohjelmalle. Ks. alkuperäinen tehtävänanto:
"Create a program which is able to calculate and output (as double value, with 3 decimals) the
average value of the integer numbers given by the user. New numbers are asked until the user
enters a negative value, for example -1. "

Tai jos oikein haluaa tulkita kuin piru raamattua, niin liukuluvut vaan skipattaisiin hiljaisesti (elleivät ole negatiivisia) ja keskiarvo laskettaisiin pelkille kokonaisluvuille. :D
 
Viimeksi muokattu:
Liittynyt
16.11.2020
Viestejä
2 565
Miten 1.124 + 4.238 on kokonaisluku?
Luetaan tosiaan se tehtävänanto :D

"Create a program which is able to calculate and output (as double value, with 3 decimals) the average value of the integer numbers given by the user "

Keskiarvo voi olla desimaaliluku, syötteet kokonaislukuja.

muoks. ja hidas.
 

Mustalaa

Lepakkona Ozzfesteillä
Liittynyt
17.10.2016
Viestejä
517
Osattaisiinko täällä neuvoa Excelin kanssa? Mulla on työkirjassa vertailtu asioita, jokainen kohde omana sarakkeena ja vertailukriteeri rivinsä. Soluissa on tekstiä ja taustaväri. Saanko jotenkin määritettyä taustaväreille arvot (tekstit säilyttäen)? Eli vihreä tausta on +1, keltainen -2, valkoinen/ei täyttöä 0 jne. Ja arvojen perusteella tulostettua taulukon loppuun sitten pisteet kullekin sarakkeelle, vai meneekö helpommin laskemalla käsin :btooth:?
 
Liittynyt
25.10.2016
Viestejä
89
Osattaisiinko täällä neuvoa Excelin kanssa? Mulla on työkirjassa vertailtu asioita, jokainen kohde omana sarakkeena ja vertailukriteeri rivinsä. Soluissa on tekstiä ja taustaväri. Saanko jotenkin määritettyä taustaväreille arvot (tekstit säilyttäen)? Eli vihreä tausta on +1, keltainen -2, valkoinen/ei täyttöä 0 jne. Ja arvojen perusteella tulostettua taulukon loppuun sitten pisteet kullekin sarakkeelle, vai meneekö helpommin laskemalla käsin :btooth:?
Tän mukaan pitäisi onnistua. Helpommasta en sitten tiedä näillä tiedoilla.
 
Liittynyt
07.01.2021
Viestejä
678
En oikein tunnu löytävän tähän mitään best practices-ohjetta, joten mikä on paras/normaali tapa hoitaa tämä?

Eli minulla on nappi, jolla poistetaan kuva tietokannasta. Tämä toiminnallisuus tietysti kannattaa tehdä JS-funktiolla, jotta näkymää ei tarvitse ladata uudestaan. Joten kannattaako tuo nappi rekisteröidä jollain classilla, siis $("#removebutton").onClick() { ...} vai lisätä onClick buttonin attribuutiksi (onClick="removeImage("/removeCover") jne)? On muutamia erilaisia kuvia ja ne on linkattu eri paikoissa, joten pitää parametrisoida tuo kutsuttava funktio (ensimmäisessä vaihtoehdossa varmaankin sijoittaisin tuon routen data-save-attribuuttiin).

Kumpi on suositeltavampi tapa vai onko tällä väliä?
 
Liittynyt
18.10.2016
Viestejä
272
En oikein tunnu löytävän tähän mitään best practices-ohjetta, joten mikä on paras/normaali tapa hoitaa tämä?

Eli minulla on nappi, jolla poistetaan kuva tietokannasta. Tämä toiminnallisuus tietysti kannattaa tehdä JS-funktiolla, jotta näkymää ei tarvitse ladata uudestaan. Joten kannattaako tuo nappi rekisteröidä jollain classilla, siis $("#removebutton").onClick() { ...} vai lisätä onClick buttonin attribuutiksi (onClick="removeImage("/removeCover") jne)? On muutamia erilaisia kuvia ja ne on linkattu eri paikoissa, joten pitää parametrisoida tuo kutsuttava funktio (ensimmäisessä vaihtoehdossa varmaankin sijoittaisin tuon routen data-save-attribuuttiin).

Kumpi on suositeltavampi tapa vai onko tällä väliä?
Tein vanilla-esimerkin aiheeseen liittyen:
Eli IMO helpompaa on rekisteröidä tapahtumankuuntelija classNamen perusteella ja sitten hakea kohdereitti dataset:istä.
 
Liittynyt
16.10.2016
Viestejä
543
Tein vanilla-esimerkin aiheeseen liittyen:
Eli IMO helpompaa on rekisteröidä tapahtumankuuntelija classNamen perusteella ja sitten hakea kohdereitti dataset:istä.
Nyt on kaunista koodia :thumbsup: ...ja samaa mieltä, event listener on siistein vaihtoehto.
 
Liittynyt
07.01.2021
Viestejä
678
Onko muuten json2html.py hyvä moduli tai onko jotain muita vaihtoehtoja? Minun googlefuni ei tunnu oikein löytävän mitään muuta. Vaihtoehto on kai lähinnä kirjoittaa käsittely kokonaan itse.

Tuo voisi kuitenkin olla seuraava refaktorointi. Nyt rumasti koko html-rimpsu generoidaan ORM:ssa suorituskykysyistä. Jos teen saman templaatissa, niin isojen sivujen lataaminen hidastuu rutkasti. Nyt siellä templaatissa vaan sanotaan

{{ works|safe }}

ja saadaan koko kirjalista tuupattua. Mutta eihän tuo rakenne hyvä ole. Voisi jossain vaiheessa kirjoittaa API:n joka palauttaa saman datan JSON:na ja muotoilla se frontissa halutun näköiseksi.
 
Liittynyt
07.01.2021
Viestejä
678
Aivan ylivoimaisesti eniten tässä JS/DOM-hommassa vituttaa se, että jos on joku ongelma, ja sitä googlaa, saa miljoona eri vaihtoehtoa, joista yksikään ei sitten toimi. Menee ihan vitusti aikaa kun kokeilee kaikki ei-toimivat vaihtoehdot läpi. En tiedä yhtään toista ohjelmointiympäristöä, jossa on lähellekään yhtä paljon rikkinäisiä ohjeita. Nytkin pitäisi niinkin simppeli juttu saada tehtyä kuin tsekattua, että onko elementille tietty attribuutti ja jos on, tehdä jotain. En edes enää tiedä, montako eri vaihtoehtoa olen kokeillut, mutta mikään ei tunnu toimivan. attr() ei tunnu toimivan, eikä hasAttr(). hasAttribute():sta selain valittaa, että ei sellaista olekaan. Ei toimi nämäkään: How to Check If an Element Has Attribute Using jQuery and JavaScript?. Ja tällaistakin syntaksia ehdotettiin: $(this).is("[name]"). Juu, ei.

Toinen juttu on sitten se, että en ole vielä törmännyt kuvaukseen siitä, miten sivun lataus tapahtuu. Lähinnä kiinnostaisi se, että voiko minulle olla lukematon määrä $(document).ready()-funktioita?

Ja vielä: tarvitseeko noiden $(".xxx").on() -tyyppisten jquery-juttujen olla ready():n sisässä vai ajetaanko ne kaikki automaattisesti sivun latauksessa?

Tällä hetkellä olen menossa tällaisessa hässäkässä:
Koodi:
    $(".btnRemove").on("click", function (e) {
      e.preventDefault();
      var curr = $(this);
      if (confirm("Oletko varma?")) {
        img_src = $(this).data("replace");
        $.ajax({
          type: "POST",
          dataType: "json",
          url: $(this).data("save"),
          data: {
            itemId: JSON.stringify(itemId),
          },
          success: function (data) {
            if (curr.attr("replace")) {
              $("#image").attr("src", img_src);
            }
          },
        });
      }
    });
Ilman tuota viimeistä ehtoa homma toimii, joten siinä ei vika ole. Ja tuo curr on tuossa kun alkoi vaikuttaa, että $(this) ei ole jostain syystä enää voimassa success-kohdassa.
 
Liittynyt
21.10.2016
Viestejä
9 054
Aivan ylivoimaisesti eniten tässä JS/DOM-hommassa vituttaa se, että jos on joku ongelma, ja sitä googlaa, saa miljoona eri vaihtoehtoa, joista yksikään ei sitten toimi. Menee ihan vitusti aikaa kun kokeilee kaikki ei-toimivat vaihtoehdot läpi. En tiedä yhtään toista ohjelmointiympäristöä, jossa on lähellekään yhtä paljon rikkinäisiä ohjeita. Nytkin pitäisi niinkin simppeli juttu saada tehtyä kuin tsekattua, että onko elementille tietty attribuutti ja jos on, tehdä jotain. En edes enää tiedä, montako eri vaihtoehtoa olen kokeillut, mutta mikään ei tunnu toimivan. attr() ei tunnu toimivan, eikä hasAttr(). hasAttribute():sta selain valittaa, että ei sellaista olekaan. Ei toimi nämäkään: How to Check If an Element Has Attribute Using jQuery and JavaScript?. Ja tällaistakin syntaksia ehdotettiin: $(this).is("[name]"). Juu, ei.

Toinen juttu on sitten se, että en ole vielä törmännyt kuvaukseen siitä, miten sivun lataus tapahtuu. Lähinnä kiinnostaisi se, että voiko minulle olla lukematon määrä $(document).ready()-funktioita?

Ja vielä: tarvitseeko noiden $(".xxx").on() -tyyppisten jquery-juttujen olla ready():n sisässä vai ajetaanko ne kaikki automaattisesti sivun latauksessa?

Tällä hetkellä olen menossa tällaisessa hässäkässä:
Koodi:
    $(".btnRemove").on("click", function (e) {
      e.preventDefault();
      var curr = $(this);
      if (confirm("Oletko varma?")) {
        img_src = $(this).data("replace");
        $.ajax({
          type: "POST",
          dataType: "json",
          url: $(this).data("save"),
          data: {
            itemId: JSON.stringify(itemId),
          },
          success: function (data) {
            if (curr.attr("replace")) {
              $("#image").attr("src", img_src);
            }
          },
        });
      }
    });
Ilman tuota viimeistä ehtoa homma toimii, joten siinä ei vika ole. Ja tuo curr on tuossa kun alkoi vaikuttaa, että $(this) ei ole jostain syystä enää voimassa success-kohdassa.
Tämä luettu? .attr() | jQuery API Documentation

Voipi olla, että sun curr.attr("replace") on undefined? Onko tolla attribuutilla joku arvo domissa vai onko määrittelemätön? console.logilla vaikka tsekkaat..
 
Liittynyt
17.10.2016
Viestejä
4 589
Ja tuo curr on tuossa kun alkoi vaikuttaa, että $(this) ei ole jostain syystä enää voimassa success-kohdassa.
Se ei toimi siksi, että noin määritellyllä funktiolla kuin sinulla tuossa successissa on, on aina oma scopensa, eli this funktion sisällä viittaa aina funktioon itseensä.

Käytä arrow function -notaatiota tuollaisissa callbackeissa niin pääset ongelmasta eroon. Arrow funktioilla ei ole omaa scopea. Arrow function expressions - JavaScript | MDN

Tämä ei tosin varmaan itse ongelmaa ratkaise. Siihen auttanee että tuuttaat konsoliin tuolla successissa kaiken millä voi asiaan olla vaikutusta.

Sitä tosin ihmettelen mikä tuon attribuuttitestin tarkoitus tuolla lopussa on? Ensin tehdään postaus jonnekin ja sen jälkeen muutetaan UI:ta ehdollisesti sen mukaan mitä DOMissa on (eikä sen mukaan mitä post antaa vastaukseksi)?

Koodi:
    $(".btnRemove").on("click", function (e) {
      e.preventDefault();
      if (confirm("Oletko varma?")) {
        img_src = $(this).data("replace");
        $.ajax({
          type: "POST",
          dataType: "json",
          url: $(this).data("save"),
          data: {
            itemId: JSON.stringify(itemId),
          },
          success: (data) => {
            if ($(this).attr("replace")) {
              $("#image").attr("src", img_src);
            }
          },
        });
      }
    });
 
Liittynyt
07.01.2021
Viestejä
678
Idea on siis se, että voisin käyttää tuota samaa funktiota muuhunkin. Bäkkärihän ei sitä voi taas tietää, miltä UI näyttää. Pidän tuota successia eräänlaisena postprosessointina, eli riippuen siitä, mitä tehdään, tuossa voi tehdä DOM:lle erilaisia juttuja, ei vain korvata yksi img src joksikin muuksi.
 
Liittynyt
11.09.2020
Viestejä
9
Miten saa Pythonilla seuraavasta tekstistä kolmannen rivin numerot talteen regexin avulla? Saan tuon nimen talteen vlan 100 tekstin alta, mutta kun yritän kolmatta riviä, niin tulee: re.error: look-behind requires fixed-width pattern. Yritin laittaa sulkuja ja noita lookbehindejä erikseen eikä mikään toimi.

Tässä oma koodi:
Python:
with open(tiedosto, "r") as file:
config = file.read()
pattern_access = re.compile(r'(?<=\nvlan\W100\n.*\portti\W).*')
matches_access = pattern_access.findall(config)
Teksti on:

vlan 100
name "Nimi"
portti 1,2,3
 
Liittynyt
17.10.2016
Viestejä
1 115
Miten saa Pythonilla seuraavasta tekstistä kolmannen rivin numerot talteen regexin avulla? Saan tuon nimen talteen vlan 100 tekstin alta, mutta kun yritän kolmatta riviä, niin tulee: re.error: look-behind requires fixed-width pattern. Yritin laittaa sulkuja ja noita lookbehindejä erikseen eikä mikään toimi.

Tässä oma koodi:
Python:
with open(tiedosto, "r") as file:
config = file.read()
pattern_access = re.compile(r'(?<=\nvlan\W100\n.*\portti\W).*')
matches_access = pattern_access.findall(config)
Teksti on:

vlan 100
name "Nimi"
portti 1,2,3
Onko erityinen syy käyttää lookbehindia? Helpommalla multiline regexillä Esim.
Python:
with open(tiedosto, 'r') as file:
    config = file.read()
    pattern_access = re.compile(r'(?:vlan|name|portti)\s(.*)(?:\n|\r\n?)?', re.MULTILINE)
    matches_access = pattern_access.findall(config)
    print(f'{matches_access}')
tuottaa: ['100', '"Nimi"', '1,3,5']
 
Liittynyt
11.09.2020
Viestejä
9
Onko erityinen syy käyttää lookbehindia? Helpommalla multiline regexillä Esim.
Python:
with open(tiedosto, 'r') as file:
    config = file.read()
    pattern_access = re.compile(r'(?:vlan|name|portti)\s(.*)(?:\n|\r\n?)?', re.MULTILINE)
    matches_access = pattern_access.findall(config)
    print(f'{matches_access}')
tuottaa: ['100', '"Nimi"', '1,3,5']
Ei ole. Oman ratkaisun löysin Googlettelemalla, kun regexit ei ole oikeen hallussa. Tuossa oli semmonen suunnitelma, että portin numerosta ja vlanista tulee dictionaryn key/value pari (1:100, 2:100, 3:100 jne). Mutta, tuo sinun ratkaisu toimii, koska tuolta listasta saadaan indexillä pomittua arvot ja for loopin kautta siirrettyä tuonne dictionaryyn. Kiitos vastauksesta! :thumbsup:
 

hrk

Liittynyt
23.07.2017
Viestejä
1 730
Miten saa Pythonilla seuraavasta tekstistä kolmannen rivin numerot talteen regexin avulla? Saan tuon nimen talteen vlan 100 tekstin alta, mutta kun yritän kolmatta riviä, niin tulee: re.error: look-behind requires fixed-width pattern. Yritin laittaa sulkuja ja noita lookbehindejä erikseen eikä mikään toimi.

Tässä oma koodi:
Python:
with open(tiedosto, "r") as file:
config = file.read()
pattern_access = re.compile(r'(?<=\nvlan\W100\n.*\portti\W).*')
matches_access = pattern_access.findall(config)
Teksti on:

vlan 100
name "Nimi"
portti 1,2,3
Tällainen:

Python:
txt = "vlan 100\nname \"Nimi\"\n  portti  1,2, 123"
r = list(map(int, txt.splitlines()[2].strip().split(" ", 1)[1].split(',')))
... etsii merkkijonon 'txt' kolmannelta riviltä rivin alun mahdollisten blankkojen (strip) jälkeen ensimmäisen blankkojonon jälkeisestä rivin lopusta pilkkujen erottamat jonot, konvertoi ne kokonaisluvuiksi ja antaa tuloksen listana.

Näin minä sen tekisin. Jos jostain syystä (?) on pakko käyttää regexiä, niin esim. näin saisi saman tuloksen:

Python:
import re
txt = "vlan 100\nname \"Nimi\"\n  portti  1,2, 123"
m = re.search(".*\n.*\n\s*\w+\s+(\d+)\D+(\d+)\D+(\d+)", txt)
r = []
if m:
    for g in range(1, 4):
        r.append(m.group(g))
r = list(map(int, r))
Tuo siis aluksi skippaa kaksi riviä ja kolmannen rivin alusta ensin mahdolliset blankot, sitten vähintään yhden ei-whitespacen ja sen jälkeiset blankot, ja etsii loppurivistä kolme numerojonoa, joiden välisssä on ei-numeroita.

Nuo siis toimivat jos ja vain jos niitä lukuja etsitään nimenomaan kolmannelta riviltä, ja lukuja on rivillä regex-tapauksessa vähintään kolme. Eikä ole väliä sillä, mitä rivin alussa lukee.
 
Viimeksi muokattu:
Liittynyt
05.02.2017
Viestejä
176
Olen harjoittelemassa ohjelman säikeistämistä ja streamien käyttöä C++:lla. Ideana tässä, että thread1 suorittaisi algoritmia nopeasti ja ottaisi vain talteen mielenkiintoiset luvut myöhempää käsittelyä varten. Thread2 vastaa bufferin lukemisesta ja tässä kehitysvaiheessa ainoastaan tulostaa ne ruudulle formatoituina.

Ongelmana on, että bufferin lukeminen ja tulostaminen lakkaa toimimasta jo muutaman iteraation jälkeen:
First thread created, start collatz algorithm
Second thread, not implemented
New path length record with seed: 3 (6 steps)
New path length record with seed: 6 (7 steps)
New path length record with seed: 7 (15 steps)
New path length record with seed: 9 (18 steps)
New path length record with seed: 18 (19 steps)
New path length record with seed: 25 (22 steps)
New path length record with seed: 27 (110 steps)
New path length record with seed: 54 (111 steps)
New path length record with seed: 73 (114 steps)
New path length record with seed: 97 (117 steps)
C++:
#include <iostream>
#include <sstream>
#include <thread>
#include <mutex>
#include <tuple>
#include <climits>
#include <functional>
#include <chrono>

std::mutex mtx_stream;
bool DONE = false;

unsigned long getNextStep(const unsigned long current)
{
    return (current % 2) ? (current * 3) + 1 : (current / 2);
}

/**
 * @brief Runs the collatz conjecture algorithm for all integers (to the limit)
 *
 * @param buffer output buffer to save intresting numbers for output formatting
 */
void thread1(std::stringstream &buffer)
{
    std::cout << "First thread created, start collatz algorithm" << std::endl;

    const unsigned long guard = ULONG_MAX/4;
    unsigned long zenith=2, path_record = 0;
    unsigned long zenith_update_counter = 0, path_record_update_counter = 0;
    bool is_path_record_updated = false;

    for (unsigned long seed = 2; seed < guard; seed++){
        /* *
        if (seed % 1000000 == 0 || path_record_update_counter % 100 == 0){
            std::cout \
            << "Current seed: " << seed \
            << ", path record: " << path_record \
            << ", zenith record: " << zenith << std::endl;
        }
        /* */
        for (unsigned long i = seed, path_length = 0; i != 1 && i < guard; path_length++){
            i = getNextStep(i);
            if (i > zenith) {
                zenith = i;
                zenith_update_counter++;
            }
            if (path_length > path_record) {
                is_path_record_updated = true;
                path_record = path_length;
                path_record_update_counter++;
            }
        }
        
        if (is_path_record_updated){
            //std::cout << seed << std::endl;
            mtx_stream.lock();
            buffer << seed << " " << path_record << std::endl;
            mtx_stream.unlock();
            is_path_record_updated = false;
        }
    }
    
    std::cout << "First thread exhausted, exiting" << std::endl;
    DONE = true;
}

/** TODO:
 * @brief Save records to database (textfile)
 *
 */
void thread2(std::stringstream &buffer)
{
    std::cout << "Second thread, not implemented" << std::endl;
    unsigned int seed, path_length;//std::string seed, path_length;
    /* */
    while (!DONE){
        mtx_stream.lock();
        while (buffer >> seed >> path_length) {
            //buffer.clear();
            std::cout <<"New path length record with seed: " << seed \
            << " (" << path_length << " steps)" << std::endl;
        }
        mtx_stream.unlock();

        std::this_thread::sleep_for(std::chrono::nanoseconds(10000));
    }
    /* */
    std::cout << "Second thread exhausted, exiting" << std::endl;

}


int main(void)
{
    std::stringstream buffer;

    std::thread first (thread1, std::ref(buffer));
    std::thread second (thread2, std::ref(buffer));

    first.join();
    second.join();
    return 0;
}

Olen kokeillut tätä mutexilla ja ilman, eikä sillä ole mitään vaikutusta. Mielenkiintoisena yksityiskohtana on tulostettavien rivien määrä - eri suorituskerroilla saan kaikkea 5:n ja 15:sta rivin väliltä.

Onko ideoita mitä teen väärin?
 
Liittynyt
02.09.2018
Viestejä
47
while (buffer >> seed >> path_length) {
Minua kiinostaa rivi:
while (buffer >> seed >> path_length) {

Mitä tämä tekee? C++ doc: while ( expression ) ;

expression >>

The next example shows right-shift operations with negative signed integers.

Lisäksi pitää huomata, että säikeet ovat erillisiä aliprosesseita, jotka eivät tiedä mitään toisistaan.

Itse opin aikoinani, että esim. testitulosteissa kannattaa lisätä joka rivin alkuun aikaleima esim. millisekunnin tarkkuudella sekä ko säikeen tunnus, josta voi tietää, mikä säie on kertomassa itsestään.

Edit: Ja kannattaa myös pitää ne eri source -tiedostoissa.
 
Viimeksi muokattu:
Liittynyt
14.10.2017
Viestejä
620
Olen harjoittelemassa ohjelman säikeistämistä ja streamien käyttöä C++:lla. Ideana tässä, että thread1 suorittaisi algoritmia nopeasti ja ottaisi vain talteen mielenkiintoiset luvut myöhempää käsittelyä varten. Thread2 vastaa bufferin lukemisesta ja tässä kehitysvaiheessa ainoastaan tulostaa ne ruudulle formatoituina.

Ongelmana on, että bufferin lukeminen ja tulostaminen lakkaa toimimasta jo muutaman iteraation jälkeen:
First thread created, start collatz algorithm
Second thread, not implemented
New path length record with seed: 3 (6 steps)
New path length record with seed: 6 (7 steps)
New path length record with seed: 7 (15 steps)
New path length record with seed: 9 (18 steps)
New path length record with seed: 18 (19 steps)
New path length record with seed: 25 (22 steps)
New path length record with seed: 27 (110 steps)
New path length record with seed: 54 (111 steps)
New path length record with seed: 73 (114 steps)
New path length record with seed: 97 (117 steps)
C++:
#include <iostream>
#include <sstream>
#include <thread>
#include <mutex>
#include <tuple>
#include <climits>
#include <functional>
#include <chrono>

std::mutex mtx_stream;
bool DONE = false;

unsigned long getNextStep(const unsigned long current)
{
    return (current % 2) ? (current * 3) + 1 : (current / 2);
}

/**
 * @brief Runs the collatz conjecture algorithm for all integers (to the limit)
 *
 * @param buffer output buffer to save intresting numbers for output formatting
 */
void thread1(std::stringstream &buffer)
{
    std::cout << "First thread created, start collatz algorithm" << std::endl;

    const unsigned long guard = ULONG_MAX/4;
    unsigned long zenith=2, path_record = 0;
    unsigned long zenith_update_counter = 0, path_record_update_counter = 0;
    bool is_path_record_updated = false;

    for (unsigned long seed = 2; seed < guard; seed++){
        /* *
        if (seed % 1000000 == 0 || path_record_update_counter % 100 == 0){
            std::cout \
            << "Current seed: " << seed \
            << ", path record: " << path_record \
            << ", zenith record: " << zenith << std::endl;
        }
        /* */
        for (unsigned long i = seed, path_length = 0; i != 1 && i < guard; path_length++){
            i = getNextStep(i);
            if (i > zenith) {
                zenith = i;
                zenith_update_counter++;
            }
            if (path_length > path_record) {
                is_path_record_updated = true;
                path_record = path_length;
                path_record_update_counter++;
            }
        }
        
        if (is_path_record_updated){
            //std::cout << seed << std::endl;
            mtx_stream.lock();
            buffer << seed << " " << path_record << std::endl;
            mtx_stream.unlock();
            is_path_record_updated = false;
        }
    }
    
    std::cout << "First thread exhausted, exiting" << std::endl;
    DONE = true;
}

/** TODO:
 * @brief Save records to database (textfile)
 *
 */
void thread2(std::stringstream &buffer)
{
    std::cout << "Second thread, not implemented" << std::endl;
    unsigned int seed, path_length;//std::string seed, path_length;
    /* */
    while (!DONE){
        mtx_stream.lock();
        while (buffer >> seed >> path_length) {
            //buffer.clear();
            std::cout <<"New path length record with seed: " << seed \
            << " (" << path_length << " steps)" << std::endl;
        }
        mtx_stream.unlock();

        std::this_thread::sleep_for(std::chrono::nanoseconds(10000));
    }
    /* */
    std::cout << "Second thread exhausted, exiting" << std::endl;

}


int main(void)
{
    std::stringstream buffer;

    std::thread first (thread1, std::ref(buffer));
    std::thread second (thread2, std::ref(buffer));

    first.join();
    second.join();
    return 0;
}

Olen kokeillut tätä mutexilla ja ilman, eikä sillä ole mitään vaikutusta. Mielenkiintoisena yksityiskohtana on tulostettavien rivien määrä - eri suorituskerroilla saan kaikkea 5:n ja 15:sta rivin väliltä.

Onko ideoita mitä teen väärin?
Sulla on siellä kommentoituna
Koodi:
//buffer.clear();
Ongelma (sen lisäksi että se on kommentoituna) on siinä, että clear suoritetaan vain silloin, kun whilen ehto on tosi. Ja ehto on tosi silloin kun stringstreamin tila on "good". Mutta silloin ei ole mitään clearattavaa! Eli laita se clear while-loopin jälkeen:
Koodi:
        mtx_stream.lock();
        while (buffer >> seed >> path_length) {
            std::cout <<"New path length record with seed: " << seed \
            << " (" << path_length << " steps)" << std::endl;
        }
        buffer.clear();
        mtx_stream.unlock();
Ja tuo clear tarvitaan siis sen takia, että thread1 ei suostu kirjoittamaan bufferiin, jos sen tila on "eof" eli end-of-file (tai oikeastaan end-of-stream). Clearin jälkeen tilasta tulee jälleen "good" jolloin bufferiin voi kirjoittaa.

edit: Tarkalleen ottaen stringstreamin tilat on vähän monimutkaisempia kuin yllä esitetty yksinkertaistettu good vs.eof. On mahdollista löytää streamin loppu siten, että tila säilyy hyvänä. Mutta yllä olevassa koodissa sen ei pitäisi koskaan tapahtua, koska streamin lopun osuessa kohdalle seediin ja path_lengthiin ei voi kirjoittaa, eli eof on käytännössä sama asia kuin fail, joka on käytännnössä sama kuin ei-good.
 
Viimeksi muokattu:
Liittynyt
09.03.2017
Viestejä
37
Terve! Oon hetken paininut henkilökohtaisen harjoitteluprojektin kanssa. Tuon APIn kautta saan kyseisten tavaroiden "rarityn" haettua. Haluaisin tavaran rarityn mukaan määrittää kortille taustavärin. Tällä hetkellä olen koittanut käyttää if elseä siihen värin hakemiseen. (Löytyy tuon codepenistä kommentoituna.)
Täytyisi varmaan käyttää jonkinnäköistä silmukkaa, koska tän hetkisellä ratkaisulla kaikille korteille tulee sama väri. Consoli kuitenkin kertoo että se hakee ne oikeat arvot sieltä apista.
Oma taito ei riitä vielä saamaan silmukkaa toimimaan kun kyseessä on api jossa on monia objekteja. Osaisiko kukaan auttaa/Tökkästä oikeaan suuntaan?

 
Viimeksi muokattu:
Liittynyt
21.10.2016
Viestejä
9 054
Terve! Oon hetken paininut henkilökohtaisen harjoitteluprojektin kanssa. Tuon APIn kautta saan kyseisten tavaroiden "rarityn" haettua. Haluaisin tavaran rarityn mukaan määrittää kortille taustavärin. Tällä hetkellä olen koittanut käyttää if elseä siihen värin hakemiseen. (Löytyy tuon codepenistä kommentoituna.)
Täytyisi varmaan käyttää jonkinnäköistä silmukkaa, koska tän hetkisellä ratkaisulla kaikille korteille tulee sama väri. Consoli kuitenkin kertoo että se hakee ne oikeat arvot sieltä apista.
Oma taito ei riitä vielä saamaan silmukkaa toimimaan kun kyseessä on api jossa on monia objekteja. Osaisiko kukaan auttaa/Tökkästä oikeaan suuntaan?


Vaihdat css-luokan .card väriä, et yksittäisten korttien väriä. => kaikilla korteilla loopin viimeisen kortin väri.
 
Liittynyt
05.02.2017
Viestejä
176
Minua kiinostaa rivi:
while (buffer >> seed >> path_length) {

Mitä tämä tekee? C++ doc: while ( expression ) ;
Ottaa bufferista kaksi whitespacella erotettua arvoa ja asettaa ne muuttujiin seed ja path_length. Tämän jälkeen while-silmukka evaluoi edellisen operaation paluuarvon - jonka sisältöä en näköjään ole kunnolla sisäistänyt. (katso alla oleva lainaus)
Ja tuo clear tarvitaan siis sen takia, että thread1 ei suostu kirjoittamaan bufferiin, jos sen tila on "eof" eli end-of-file (tai oikeastaan end-of-stream). Clearin jälkeen tilasta tulee jälleen "good" jolloin bufferiin voi kirjoittaa.

edit: Tarkalleen ottaen stringstreamin tilat on vähän monimutkaisempia kuin yllä esitetty yksinkertaistettu good vs.eof. On mahdollista löytää streamin loppu siten, että tila säilyy hyvänä. Mutta yllä olevassa koodissa sen ei pitäisi koskaan tapahtua, koska streamin lopun osuessa kohdalle seediin ja path_lengthiin ei voi kirjoittaa, eli eof on käytännössä sama asia kuin fail, joka on käytännnössä sama kuin ei-good.
Kiitos todella paljon selventävästä vastauksesta, alkoi pelittämään. :tup:
Näköjään olen ylenkatsonut streamien sisäistä toimintaa aika huolella ja olettanut liikaa. Näitä selitetään hyvin harvoissa netin ilmaisissa lähteissä perinpohjaisesti ja tarkempi toiminta jää tuntemattomaksi.
 
Liittynyt
21.10.2016
Viestejä
9 054
Kiitos vastauksesta! Sain ongelmaan ratkaisun Stack overflown puolella. Linkki jos joku joskus painii saman ongelman kanssa.
Juu, itse täs kännyllä, nii ei ole esimerkkiä antaa. Mut ton sun koodin perusteella, ku värit bäkkäristä tulee ja on tiedossa, nii voisit esim. niitä vastaavat css-luokat tehdä ja asettaa kortille suoraan ilman ehtolauseita. Esim. color-common, color-grey jne. Muutenki semmonen yleinen värisetti hyvä lähestymistapa. Esim.color-primary, color-secondary, color-grey-1,color-grey-2,color-card-1,color-card-2 jne. Helppo sit jälkikäteen muutella.
 
Liittynyt
11.09.2020
Viestejä
9
Tällainen:

Python:
txt = "vlan 100\nname \"Nimi\"\n  portti  1,2, 123"
r = list(map(int, txt.splitlines()[2].strip().split(" ", 1)[1].split(',')))
... etsii merkkijonon 'txt' kolmannelta riviltä rivin alun mahdollisten blankkojen (strip) jälkeen ensimmäisen blankkojonon jälkeisestä rivin lopusta pilkkujen erottamat jonot, konvertoi ne kokonaisluvuiksi ja antaa tuloksen listana.

Näin minä sen tekisin. Jos jostain syystä (?) on pakko käyttää regexiä, niin esim. näin saisi saman tuloksen:

Python:
import re
txt = "vlan 100\nname \"Nimi\"\n  portti  1,2, 123"
m = re.search(".*\n.*\n\s*\w+\s+(\d+)\D+(\d+)\D+(\d+)", txt)
r = []
if m:
    for g in range(1, 4):
        r.append(m.group(g))
r = list(map(int, r))
Tuo siis aluksi skippaa kaksi riviä ja kolmannen rivin alusta ensin mahdolliset blankot, sitten vähintään yhden ei-whitespacen ja sen jälkeiset blankot, ja etsii loppurivistä kolme numerojonoa, joiden välisssä on ei-numeroita.

Nuo siis toimivat jos ja vain jos niitä lukuja etsitään nimenomaan kolmannelta riviltä, ja lukuja on rivillä regex-tapauksessa vähintään kolme. Eikä ole väliä sillä, mitä rivin alussa lukee.
Oli minulta vähän huonosti selitetty minun ongelma. Eli, tilanne on semmoinen että minulla on config-tiedosto, mistä pitää lukea nuo rivit ja samassa tiedostossa on muita samanlaisia rivejä. Olen saanut jo luetua dictionaryyn key:value pariksi vlan id:n ja nimen (100:vlan 100, 200:vlan 200, 300:vlan 300). Nyt tästä dictionarystä luetaan key valuet (for loopissa) ja lisätään se muuttujan avulla tuonne regex rimpsun sisälle, että se hakee tietyn vlanin alta nuo portit. Sitten ne (untagged/tagged) taas käsitellään for loopissa siten, että portin numero menee keyksi ja vlan id valueksi omissa dictionareissa. @Barbarossa ehdotus multilinestä oli hyvä, mutta en keksinyt itse järkevää tapaa miten saan tiedot oikein, jos vlan xxx rivin alta puuttuu joku rivi (name, untagged tai tagged).

Eli tiedosto näyttää tältä:

vlan 100
name "vlan 100"
untagged 1,3,4
tagged 27,28

vlan 200
name "vlan 200"
untagged 2,4,6
tagged 27,28

vlan 300
name "vlan 300"
untagged 7,9,11
tagged 27,28
 
Liittynyt
17.10.2016
Viestejä
5 658
Oli minulta vähän huonosti selitetty minun ongelma. Eli, tilanne on semmoinen että minulla on config-tiedosto, mistä pitää lukea nuo rivit ja samassa tiedostossa on muita samanlaisia rivejä. Olen saanut jo luetua dictionaryyn key:value pariksi vlan id:n ja nimen (100:vlan 100, 200:vlan 200, 300:vlan 300). Nyt tästä dictionarystä luetaan key valuet (for loopissa) ja lisätään se muuttujan avulla tuonne regex rimpsun sisälle, että se hakee tietyn vlanin alta nuo portit. Sitten ne (untagged/tagged) taas käsitellään for loopissa siten, että portin numero menee keyksi ja vlan id valueksi omissa dictionareissa. @Barbarossa ehdotus multilinestä oli hyvä, mutta en keksinyt itse järkevää tapaa miten saan tiedot oikein, jos vlan xxx rivin alta puuttuu joku rivi (name, untagged tai tagged).

Eli tiedosto näyttää tältä:

vlan 100
name "vlan 100"
untagged 1,3,4
tagged 27,28

vlan 200
name "vlan 200"
untagged 2,4,6
tagged 27,28

vlan 300
name "vlan 300"
untagged 7,9,11
tagged 27,28
Onko sulla joku erityinen syy käyttää regexiä tässä? Tuo olisi aika suoraviivainen vaan pilkkoa suoraan osiin esim:
Python:
txt = 'vlan 100\nname "vlan 100"\nuntagged 1,3,4\ntagged 17,18\n\nvlan 200\nname "vlan 200"\nuntagged 1,3,4\ntagged 27,28\n\nvlan 300\nname "vlan 300"\ntagged 37,38'

vlans = txt.split("\n\n")
vlan_list = []
for vlan in vlans:
    lines = vlan.split("\n")
    prop_dict = {}
    for line in lines:
        key, value = line.split(" ", 1)
        prop_dict[key] = value
    
    vlan_list.append(prop_dict)

print(vlan_list)
Koodi:
[
    {'vlan': '100', 'name': '"vlan 100"', 'untagged': '1,3,4', 'tagged': '17,18'},
    {'vlan': '200', 'name': '"vlan 200"', 'untagged': '1,3,4', 'tagged': '27,28'},
    {'vlan': '300', 'name': '"vlan 300"', 'tagged': '37,38'}
]
 

hrk

Liittynyt
23.07.2017
Viestejä
1 730
Oli minulta vähän huonosti selitetty minun ongelma. Eli, tilanne on semmoinen että minulla on config-tiedosto, mistä pitää lukea nuo rivit ja samassa tiedostossa on muita samanlaisia rivejä. Olen saanut jo luetua dictionaryyn key:value pariksi vlan id:n ja nimen (100:vlan 100, 200:vlan 200, 300:vlan 300). Nyt tästä dictionarystä luetaan key valuet (for loopissa) ja lisätään se muuttujan avulla tuonne regex rimpsun sisälle, että se hakee tietyn vlanin alta nuo portit. Sitten ne (untagged/tagged) taas käsitellään for loopissa siten, että portin numero menee keyksi ja vlan id valueksi omissa dictionareissa. @Barbarossa ehdotus multilinestä oli hyvä, mutta en keksinyt itse järkevää tapaa miten saan tiedot oikein, jos vlan xxx rivin alta puuttuu joku rivi (name, untagged tai tagged).

Eli tiedosto näyttää tältä:

vlan 100
name "vlan 100"
untagged 1,3,4
tagged 27,28

vlan 200
name "vlan 200"
untagged 2,4,6
tagged 27,28

vlan 300
name "vlan 300"
untagged 7,9,11
tagged 27,28
Juu, oli todella huonosti selitetty. Eikä uusi selitys ole juurikaan parempi, kun et vieläkään kuvaa mitä oikeasti haluat saada aikaan. Edupin ehdotus on periaatteessa toimiva, mutta se sekoaa jos riviryhmien välissä on useampia tyhjiä rivejä, tai jos rivien alussa on tyhjää, eikä se tee mitään niille porttinumeroiksi olettamilleni tagged/untagged-rivien luvuille. Mitä niille pitäisi tehdä?

Setämäisesti ehdotan, että unohda hetkeksi mitä tiedät python-dictionaryistä ja regular expressionneista, ja kuvaa vaikkapa ihan suomen kielellä syötteen ja halutun tulosteen sisältö ja rakenne.
 
Liittynyt
17.10.2016
Viestejä
5 658
Juu, oli todella huonosti selitetty. Eikä uusi selitys ole juurikaan parempi, kun et vieläkään kuvaa mitä oikeasti haluat saada aikaan. Edupin ehdotus on periaatteessa toimiva, mutta se sekoaa jos riviryhmien välissä on useampia tyhjiä rivejä, tai jos rivien alussa on tyhjää, eikä se tee mitään niille porttinumeroiksi olettamilleni tagged/untagged-rivien luvuille. Mitä niille pitäisi tehdä?

Setämäisesti ehdotan, että unohda hetkeksi mitä tiedät python-dictionaryistä ja regular expressionneista, ja kuvaa vaikkapa ihan suomen kielellä syötteen ja halutun tulosteen sisältö ja rakenne.
No juu, tuo splittausehto nyt helppo muuttaa jos konffitiedosto ei olekaan aina määrämuotoinen, vaan voi sisältää jotain tuollaisia erikoisuuksia. Mutta joku säännönmukaisuus siinäkin on aina pakko olettaa, vaikka tähän nyt väkisin regexiä käyttäisi.

Jos haluaisi jonkun oikeasti toimivan kilkkeen, niin pitäisi tosiaan tietää että mitä tuolla nyt oikeasti halutaan tehdä. Erityisesti se että mitä saa siltä syötteeltä olettaa ja mihin muotoon nuo tarvitsee lopulta saada.
 
Liittynyt
17.10.2016
Viestejä
1 115
Kuten yllä jo mainittiin, tuossa ei oikein täysin selviä että mikä on tavoite ja mistä se halutaan kaivaa. En minäkään tähän lähtisi regexiä vääntämään.

Mutta jos tuon tiedoston rakenne on säännöllinen, se. lohkojen välissä on yksi tyhjä rivi ja lohkossa vähintään vlan-rivi niin voisi tehdä jotain tämänsuuntaistakin:
Python:
import shlex
import os

def to_dict(l):
    i = iter(l)
    return dict(zip(i, i))

def read_config(cf):
    with open(cf, 'r') as file:
        config = file.read().strip()
    blocks = [to_dict(shlex.split(block)) for block in config.split(os.linesep*2)]
    config = {}
    for b in blocks:
        vlan = int(b.pop('vlan'))
        config[vlan] = b
    return config
 
Liittynyt
11.09.2020
Viestejä
9
Onko sulla joku erityinen syy käyttää regexiä tässä?.
On. Tämä on tekstipohjainen konfiguraatio, missä on näitten rivien ylä- / alapuolella muita globaaleja komentoja, niin pitäisi poimia juuri nuo rivit. Kiitoksia kaikille vastanneille jo etukäteen kärsivällisyydestä. :thumbsup:
 
Liittynyt
11.09.2020
Viestejä
9
Juu, oli todella huonosti selitetty. Eikä uusi selitys ole juurikaan parempi, kun et vieläkään kuvaa mitä oikeasti haluat saada aikaan. Edupin ehdotus on periaatteessa toimiva, mutta se sekoaa jos riviryhmien välissä on useampia tyhjiä rivejä, tai jos rivien alussa on tyhjää, eikä se tee mitään niille porttinumeroiksi olettamilleni tagged/untagged-rivien luvuille. Mitä niille pitäisi tehdä?

Setämäisesti ehdotan, että unohda hetkeksi mitä tiedät python-dictionaryistä ja regular expressionneista, ja kuvaa vaikkapa ihan suomen kielellä syötteen ja halutun tulosteen sisältö ja rakenne.
Minun pitää lukea tiedostosta nuo rivit ja muuttaa ne eri muotoon, mitkä kirjoitetaan toiseen tiedostoon. Eli tästä tulee ohjelma mikä muuttaa konfiguration toiseen laitevalmistajan muotoon. Olisin pistänyt tähän mallikonfiguraation, mutta ei ollut yhtään tallessa.

Eli:

---- TÄMÄ TEKSTI ON KONFIGURAATION KESKELLÄ, ELI TEKSTIÄ ON YLÄ-/ ALAPUOLELLA (GLOBAALIT KOMENNOT YMS) ----

vlan 100
untagged 1,2
tagged 25

---------------------------------------------------------------------------------------------------------------------------------------

Poimitaan edellisestä konfiguraatiosta tiedot ja muutetaan alla olevaan muotoon. Tämä kirjoitetaan uuteen tiedostoon, josta tulee toisen laitevalmistajan konfiguraatio:

interface Gigabitethernet1/0/1
switchport mode access
switchport acces vlan 100

interface Gigabitethernet1/0/2
switchport mode access
switchport acces vlan 100

interface Gigabitethernet1/0/25
switchport mode trunk
switchport trunk allowed vlan 100
 
Liittynyt
17.10.2016
Viestejä
5 658
On. Tämä on tekstipohjainen konfiguraatio, missä on näitten rivien ylä- / alapuolella muita globaaleja komentoja, niin pitäisi poimia juuri nuo rivit. Kiitoksia kaikille vastanneille jo etukäteen kärsivällisyydestä. :thumbsup:
Okei, no tossa sulle nyt regex-hirviö tuohon mikä perkaa nuo kaikki sulle johonkin rakenteiseen muotoon mistä saat ne eteenpäin:
Python:
txt = 'vlan 100\nname "vlan 100"\nuntagged 1,2,3\ntagged 11,12\n\nvlan 200\nname "vlan 200"\nuntagged 4,5\ntagged 21,22\n\nvlan 300\nname "vlan 300"\ntagged 31,32,33\n\nvlan 400\ntagged 41,42'
pattern = re.compile(r'vlan\s(\w+)(?:\nname\s"(.+?)")?(?:\nuntagged\s([\w,]*))?(?:\ntagged\s([\w,]*))?', re.MULTILINE)
print(re.findall(pattern, txt))
Koodi:
[
    ('100', 'vlan 100', '1,2,3', '11,12'),
    ('200', 'vlan 200', '4,5', '21,22'),
    ('300', 'vlan 300', '', '31,32,33'),
    ('400', '', '', '41,42')
]
Toi on edelleen vähän jäätävä tapa toteuttaa tuo, mutta varmaan auttanee pääsemään eteenpäin. Käytännössä tuolla siis luodaan non-capturing groupit tuolla (?: ) -notaatiolla, ja sen ko. non-capturing-groupin perässä ? sitä varten jos ko. arvoa ei aina konffista löydy. Niiden non-capturing-groupien sisällä on sitten perus capturing group mikä poimii ne halutut arvot talteen, jos se ulompi ryhmä nyt sitten on olemassa.

EDIT: Ainiin, nimikin sai puuttua. Muokattu pikkusen tuota, niin että senkin saa skipata. Vai oliko sitä nyt sitten olemassakaan lopulta?
 
Viimeksi muokattu:

hrk

Liittynyt
23.07.2017
Viestejä
1 730
Okei, no tossa sulle nyt regex-hirviö tuohon mikä perkaa nuo kaikki sulle johonkin rakenteiseen muotoon mistä saat ne eteenpäin:
Python:
txt = 'vlan 100\nname "vlan 100"\nuntagged 1,2,3\ntagged 11,12\n\nvlan 200\nname "vlan 200"\nuntagged 4,5\ntagged 21,22\n\nvlan 300\nname "vlan 300"\ntagged 31,32,33\n\nvlan 400\ntagged 41,42'
pattern = re.compile(r'vlan\s(\w+)(?:\nname\s"(.+?)")?(?:\nuntagged\s([\w,]*))?(?:\ntagged\s([\w,]*))?', re.MULTILINE)
print(re.findall(pattern, txt))
Koodi:
[
    ('100', 'vlan 100', '1,2,3', '11,12'),
    ('200', 'vlan 200', '4,5', '21,22'),
    ('300', 'vlan 300', '', '31,32,33'),
    ('400', '', '', '41,42')
]
Toi on edelleen vähän jäätävä tapa toteuttaa tuo, mutta varmaan auttanee pääsemään eteenpäin. Käytännössä tuolla siis luodaan non-capturing groupit tuolla (?: ) -notaatiolla, ja sen ko. non-capturing-groupin perässä ? sitä varten jos ko. arvoa ei aina konffista löydy. Niiden non-capturing-groupien sisällä on sitten perus capturing group mikä poimii ne halutut arvot talteen, jos se ulompi ryhmä nyt sitten on olemassa.

EDIT: Ainiin, nimikin sai puuttua. Muokattu pikkusen tuota, niin että senkin saa skipata. Vai oliko sitä nyt sitten olemassakaan lopulta?
Tuo menee sekaisin, jos vaikka lisäät txtiin yhden ylimääräisen blankon ensimmäisen vlan-sanan jälkeen. Pelkkä \s matchaa vain _yhden_ spacen. Ja niin edelleen. Ihan yleisestikin neuvoisin olettamaan inputin laadusta mahdollisimman vähän, etenkin jos input on ihmisen tekemä. Ja sitten se MULTILINE-flagi: Se vaikuttaisi erikoismerkkien ^ ja $ (rivin alku ja loppu) tulkintaan, mutta kun et näitä lainkaan käytä, niin flagi on merkityksetön.

En osaa niin hyvin regexiä että viitsisin pelkästään sen keinoin yrittää inputtia siivota. Pythonilla se sensijaan sujuisi esim. näin:

Python:
txt = ('vlan  100\nname "vlan 100"\nuntagged 1,2,3\ntagged 11,12\n\n'
    ' vlan 200\nname "vlan 200"\nuntagged 4,5\ntagged 21,22\n \n\n'
    'Vlan 300\nname "vlan 300"\ntagged 31,32,33\n\n'
    'vlan 400\ntagged 41,42')

vlan  = {}      # riviniput
id = None       # nipun tunnus
for line in (x.strip() for x in txt.splitlines()):
    # riveistä on alku- ja loppublankot siivottu
    if not line:
        # tyhjä rivi lopettaa nipun
        # tyhjiä voi olla useita peräkkäin
        id = None
        continue
    else:
        # ei-tyhjä rivi lisätään vlan-dictiin
        k, v = line.split(" ", 1)
        k = k.lower()
        v = v.strip()
        # nipun ensimmäisenä pitää olla 'vlan id'
        if k == "vlan":
            if id:
                # nipun alku on jo nähty, sivuutetaan
                # (voisi olla myös fataali)
                continue
            id = v
            vlan[id] = {}
        elif id and k in ("name", "tagged", "untagged"):
            # vain jos nipun alku jo nähty
            if k in ("tagged", "untagged"):
                # arvoksi int-lista
                try:
                    v = list(map(int, v.split(',')))
                except ValueError:
                    # sivuutetaan rivi, voisi olla myös fataali
                    continue
            vlan[id][k] = v
        # muut rivit sivuutetaan

for k, v in vlan.items():
    print(k, v)
Tuossa siis syntyy dictionaryjen dictionary. Mutta edelleenkään en tiedä, miten tästä edetään siihen haluttuun lopputulokseen. Kun ei ole kerrottu mikä vastaa mitä.
 
Liittynyt
07.01.2021
Viestejä
678
Mistä sen tietää, että React-appi on Typescriptiä? Tein ohjeen mukaan uuden projektin, ja sen mukaan tuossa pitäisi automaattisesti generoitua tsconfig.json, mutta ainakaan juureen ei sellaista tule. node_modules-kansion alle tulee useampikin. Kun nämä weppihommat tuntuu vaihtuvan jatkuvasti, niin en ole varma, että onko oikeat ohjeet. Tein siis projektin komennolla

npx create-react-app suomisf-ui --typescript
 
Liittynyt
07.01.2021
Viestejä
678
Itse itselleni vastaten, eihän tuo ollut oikein, vaikka joltain sivulta tuon poimin. Oikea muoto on

npx create-react-appp suomisf-ui --template typescript

Nyt juuressa on tsconfig.json. Ja src-kansiossa on ts- ja tsx-tiedostoja.
 
Liittynyt
17.10.2016
Viestejä
5 658
Tuo menee sekaisin, jos vaikka lisäät txtiin yhden ylimääräisen blankon ensimmäisen vlan-sanan jälkeen. Pelkkä \s matchaa vain _yhden_ spacen. Ja niin edelleen. Ihan yleisestikin neuvoisin olettamaan inputin laadusta mahdollisimman vähän, etenkin jos input on ihmisen tekemä. Ja sitten se MULTILINE-flagi: Se vaikuttaisi erikoismerkkien ^ ja $ (rivin alku ja loppu) tulkintaan, mutta kun et näitä lainkaan käytä, niin flagi on merkityksetön.

En osaa niin hyvin regexiä että viitsisin pelkästään sen keinoin yrittää inputtia siivota. Pythonilla se sensijaan sujuisi esim. näin:

Python:
txt = ('vlan  100\nname "vlan 100"\nuntagged 1,2,3\ntagged 11,12\n\n'
    ' vlan 200\nname "vlan 200"\nuntagged 4,5\ntagged 21,22\n \n\n'
    'Vlan 300\nname "vlan 300"\ntagged 31,32,33\n\n'
    'vlan 400\ntagged 41,42')

vlan  = {}      # riviniput
id = None       # nipun tunnus
for line in (x.strip() for x in txt.splitlines()):
    # riveistä on alku- ja loppublankot siivottu
    if not line:
        # tyhjä rivi lopettaa nipun
        # tyhjiä voi olla useita peräkkäin
        id = None
        continue
    else:
        # ei-tyhjä rivi lisätään vlan-dictiin
        k, v = line.split(" ", 1)
        k = k.lower()
        v = v.strip()
        # nipun ensimmäisenä pitää olla 'vlan id'
        if k == "vlan":
            if id:
                # nipun alku on jo nähty, sivuutetaan
                # (voisi olla myös fataali)
                continue
            id = v
            vlan[id] = {}
        elif id and k in ("name", "tagged", "untagged"):
            # vain jos nipun alku jo nähty
            if k in ("tagged", "untagged"):
                # arvoksi int-lista
                try:
                    v = list(map(int, v.split(',')))
                except ValueError:
                    # sivuutetaan rivi, voisi olla myös fataali
                    continue
            vlan[id][k] = v
        # muut rivit sivuutetaan

for k, v in vlan.items():
    print(k, v)
Tuossa siis syntyy dictionaryjen dictionary. Mutta edelleenkään en tiedä, miten tästä edetään siihen haluttuun lopputulokseen. Kun ei ole kerrottu mikä vastaa mitä.
Niin no, niitä (tehtävänannon ulkopuolisia) poikkeuksia mitkä rikkoo ratkaisun voi tänne listata loputtomiin ihan joka ratkaisuun. Mutta kun annettu speksi on mitä on, niin sillä mennään.

Jos tuolla haluaa ottaa huomioon rikkonaisia konffeja niin sitten lisää niitä varten sitä käsittelyä. Mutta ei lähtökohtaisesti voi konffeilta odottaa että muoto on täysin vapaa ja vaikka välilyöntejä saa olla miten lystää. Eikä edes että ylimääräiset whitespacet olisi aina sellaisia mitkä saa vain jättää huomiotta.

Edelleen olen sitä mieltä että tuon toteuttaminen on regexillä typerää, mutta tuo nyt ainakin tekee sen mitä on pyydetty. Tuo sunkin ratkaisusi vaikuttaa ihan fiksulta, mutta siinäkin tosiaan tehdään aika paljon oletuksia siitä mitkä on mahdollisesti sellaisia virheitä mitkä vaan saa suoraan korjata.
 
Viimeksi muokattu:

jad

Liittynyt
22.10.2016
Viestejä
1 210
Edelleen olen sitä mieltä että tuon toteuttaminen on regexillä typerää, mutta tuo nyt ainakin tekee sen mitä on pyydetty.
+1
Yritpä vaikka puolen vuoden päästä ihmetellä, että mitä helkkaria tuollainen regex hirviö tekee. Koska kyseessä on tälläinen pieni konvertointityökalu, niin suorituskyvyllä ei liene niinkään väliä, joten itse tekisin tuollaisen tämänkaltaisella logiikalla (en nyt ala ulkomuistista koodia vääntämään, en ole aikoihin pythonia käyttänyt, niin ei tule enää selkärangasta)

1. alustetaan lista vlaneille
2. luetaan rivi config tiedostosta
3. poimitaan ensimmäinen sana rivistä, jos sana on vlan, tallennetaan mahdollinen item listaan ja luodaan uusi item
4. jos sana on name, tagged tai untagged, lisätään arvo itemiin
5. goto 2
6. kun kaikki rivit luettu ja ollaan loopista pihalla, lisätään vielä viimeinen itemi listaan

Näin syntyy hyvin yksinkertainen ja ennen kaikkea luettava koodi, jonka toimintaa ei tarvitse kummemmin ihmetellä kun siihen pitää vuoden päästä tehdä joku muutos.
 
Viimeksi muokattu:
Toggle Sidebar

Statistiikka

Viestiketjut
237 389
Viestejä
4 159 492
Jäsenet
70 409
Uusin jäsen
allun90

Hinta.fi

Ylös Bottom