- Liittynyt
- 17.10.2016
- Viestejä
- 1 202
Tähän konffifilen parsimiseenhan on yksinkertainen ja lyhyt ratkaisu:
FSM
FSM
Itse olen töissä tehnyt vastaavia harjoitteita hyödyntäen tätä CiscoConfParse -kirjastoa, joka nimestään huolimatta taipuu moneen.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
from datetime import datetime
def main():
transfer_interval = 300
while(True):
startinseconds = datetime.now().timestamp()
#...
#datan siirtoa netin yli, taulukoiden yhdistämistä, kestää ~10sec normaalisti
#koodirivejä ~60
#...
sleep_time = transfer_interval-(datetime.now().timestamp() - startinseconds)
time.sleep(sleep_time)
Tehtävän ratkaisussa joutuu tutustumaan joko säikeisiin tai tapahtumalooppiin. Pelkkä time.sleep() on liian simppeli, torkkujen aikana ohjelma ei tee mitään.Miten python pitäisi rakentaa, jos haluan syöttää uusia parametrejä while-loopissa / sleep-odotuksessa? Eli tuossa while-aikana olisi mahdollista syöttää uusi odotusaika tai 'pause' komento mikä jäädyttää loopin, tai 'exit' mikä lopettaa sen.
Pääohjelmani muodostuu esimerkin mukaisesti, ja while-looppi intervalli n. 5min. Jos on myös ehdotus millä saan absoluuttisen tarkasti tuon toteutumaan 5min välein, niin senkin voisin ottaa vastaan, vaikka ihan mielenkiinnosta miten se tehtäisiin.
Koodi:from datetime import datetime def main(): transfer_interval = 300 while(True): startinseconds = datetime.now().timestamp() #... #datan siirtoa netin yli, taulukoiden yhdistämistä, kestää ~10sec normaalisti #koodirivejä ~60 #... sleep_time = transfer_interval-(datetime.now().timestamp() - startinseconds) time.sleep(sleep_time)
import tkinter as tk
root = tk.Tk()
root.title("tämä on vain hassu esimerkki")
seconds = 10
running = False
def task():
# tämä on toistettava tehtävä
print("Täällä taas: intervalli nyt", seconds)
root.after(1000 * seconds, task)
def start():
global running, seconds
# tässä konfiguroidaan
s = input("Intervalli sekunteina? ")
if s.isdecimal(): seconds = int(s)
if not running:
running = True
task()
button = tk.Button(root, text="Toistuvaistyön\nkäynnistys",
font="Calibri 24 bold", command=start)
button.pack(padx=100, pady=100)
tk.mainloop()
Yksinkertaisesta esimerkistä tulee vielä yksinkertaisempi käytettäessä tkinterin sijasta threading-kirjastoa.Tehtävän ratkaisussa joutuu tutustumaan joko säikeisiin tai tapahtumalooppiin. Pelkkä time.sleep() on liian simppeli, torkkujen aikana ohjelma ei tee mitään.
Säikeiden käyttöön liittyy paljon kikkoja ja rajoituksia. Pythonissa on kuitenkin vakiona tkinter-framework, joka varsinaisesti on tarkoitettu graafisen käyttöliittymän tekemiseen. Sen ytimenä olevaa tapahtumalooppia voi tässäkin hyödyntää:
Python:import tkinter as tk root = tk.Tk() root.title("tämä on vain hassu esimerkki") seconds = 10 running = False def task(): # tämä on toistettava tehtävä print("Täällä taas: intervalli nyt", seconds) root.after(1000 * seconds, task) def start(): global running, seconds # tässä konfiguroidaan s = input("Intervalli sekunteina? ") if s.isdecimal(): seconds = int(s) if not running: running = True task() button = tk.Button(root, text="Toistuvaistyön\nkäynnistys", font="Calibri 24 bold", command=start) button.pack(padx=100, pady=100) tk.mainloop()
import threading
def task():
print(f"Täällä taas. Intervalli nyt {seconds} sekuntia")
threading.Timer(seconds, task).start()
running = False
seconds : int
while True:
s = input("Intervalli sekunteina? ")
if s.isdecimal():
seconds = int(s)
if not running:
running = True
task()
Koska en tunne ongelmaasi, en ihan ymmärtänyt selitystäsi. Eikä minun tarvitsekaan; toivottavasti itse ymmärrät. Mutta tässä täydellisyyden vuoksi sellainen tkinter-versio, jossa on hieman parannettu käyttöliittymä. Tutkittavaksi, jos kiinnostaa.Kyllä, tuolla threadingillä rokkaa. Minulla tuossa pääohjelmassa ei ole sinänsä mitään palautettavaa konsoliin, sillä lokiin kerrytän tietoa missä mennään/mitä tehty. Tein konsoliin pienen käyttöliittymän, mistä voi lukea lokia, asettaa intervalliajan, yms parametrejä pääohjelmaan. Johtuen allekirjoittaneesta (aka python-noob), minun pythonin rakenne on vähän väärä/epäpythonmäinen, joten en tuota timeriä käyttänyt sillä tuo pääohjelma sisälsi myös virhetilanneodotuksen (joka on 30min "jäähtymisaika"). Tuo toi toisen ongelman, jos tuon pääohjelman pysäyttää/lopettaa, niin piti threadingille antaa lisämuuttuja/juokseva numero joka käynnistykselle, jotta sen sai käynnistettyä useampaan otteeseen. Tosin näin jälkikäteen, tuolla timerillä sen kyllä olisi saaanut toimimaan kun olisin vain palauttanut virhetilanne booleanin pääohjelmasta ja sen ulkopuolella hoidellut odotuksen... Voi olla että teen tuosta rakenteesta oikeamman.
Jokatapauksessa iso kiitos vinkeistä!
import tkinter as tk
root = tk.Tk()
root.title("tämä on vain hassu esimerkki")
root.resizable(0, 0)
# oletusfontti
root.option_add("*font", "Calibri 16")
frame = tk.Frame(root)
frame.pack(padx=50, pady=(20,50))
tk.Label(frame, text="Toistuvaistyö", font="Calibri 24 bold").pack(anchor="w")
f = tk.Frame(frame)
f.pack(pady=10)
tk.Label(f, text="Väliaika: ").pack(side="left")
interval = tk.Entry(f, width=4)
interval.pack(side="left")
tk.Label(f, text=" sekuntia").pack(side="left")
button = tk.Button(frame, text="Aloita", command=lambda:start())
button.pack(anchor="w")
seconds = 10
running = False
interval.delete(0, 'end')
interval.insert(0, str(seconds))
def task():
print("Tehdään jotain")
print(f"Jatketaan noin {seconds} sekunnin kuluttua")
root.after(1000 * seconds, task)
def start():
global running, seconds
s = interval.get()
if s.isdecimal(): seconds = int(s)
if not running:
running = True
button["text"] = "Jatka"
task()
tk.mainloop()
const testCalorieRange = () => {
if (formValues.targetCalories.some((i) => Number(i) < 1500)) {
return <Heading>You should have at least 1500kcal a day</Heading>;
}
}
testCalorieRange();
return //something jsx
Tuntematta nyt tarkemmin tuota koko koodia, niin miksi tuo ei palauttaisi tuota something.jsx viimeisenä?En ymmärrä miksei tuo testCalorieRange() ei koskaan palauta tuota rimpsua vaan aina komponentti palauttaa tuon //something jsx. Logilla pääsee kyllä tuon if lauseen sisälle silloin kuin kuuluukin mutta tuo <Heading> ei vaan palaudu millään.JavaScript:const testCalorieRange = () => { if (formValues.targetCalories.some((i) => Number(i) < 1500)) { return <Heading>You should have at least 1500kcal a day</Heading>; } } testCalorieRange(); return //something jsx
const testCalorieRange = () => {
if (formValues.targetCalories.some((i) => Number(i) < 1500)) {
return <Heading>You should have at least 1500kcal a day</Heading>;
} else {
return // something jsx
}
}
testCalorieRange();
Kyllähän se varmaan palauttaa sen, mutta koska sille palautteelle ei tehdä mitään niin ei se mihinkään silloin tulostu. testCalorieRange-kutsu pitäisi olla tuon return //something jsx sisällä jos sen haluaa tulostuvan.En ymmärrä miksei tuo testCalorieRange() ei koskaan palauta tuota rimpsua vaan aina komponentti palauttaa tuon //something jsx. Logilla pääsee kyllä tuon if lauseen sisälle silloin kuin kuuluukin mutta tuo <Heading> ei vaan palaudu millään.JavaScript:const testCalorieRange = () => { if (formValues.targetCalories.some((i) => Number(i) < 1500)) { return <Heading>You should have at least 1500kcal a day</Heading>; } } testCalorieRange(); return //something jsx
Sulla on vähän puutteellinen esimerkki että näkisi vähän enemmän, mitä oikeastaan haluat. Kuten tuossa jo sanottiin, se testCalorieRange(); kyllä evaluoituun oikeaksi elementiksi, mutta et palauta sitä tai käytä sitä palautusarvoa missään, joten sillä ei tehdä yhtään mitään. Se vaan katoaa käyttämättömänä. Haluat ehkä jotain tällaista, joka on aika yleinen tapa tehdä tuollaisia ehdollisia elementtejä:En ymmärrä miksei tuo testCalorieRange() ei koskaan palauta tuota rimpsua vaan aina komponentti palauttaa tuon //something jsx. Logilla pääsee kyllä tuon if lauseen sisälle silloin kuin kuuluukin mutta tuo <Heading> ei vaan palaudu millään.
function isEnoughCalories(calories) {
if ( calories >= 1500) {
return true;
}
return false;
}
const Foo = ({ calories }) => {
return (
<div>
{!isEnoughCalories(calories) && <p>You should eat more!</p>}
<p>This is shown regardless...</p>
</div>
);
}
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
saturaatio_mittaus(0);
}
}
private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) {
saturaatio_mittaus(1);
}
int saturaatio_mittaus(int seis) {
while(seis == 0) {
//ajetaan koodia
}
}
Jos tarkoitus on vaan kääntää se niin mikset seuraa sitä ohjesivun lopussa olevaa kohtaa, CLI ja Linux? Ei tarvitse minkään vieraan IDEn kanssa värkätä.Yritän kääntää Synergyä Ubuntu 21.10:lle seuraamalla näitä ohjeita: Compiling · symless/synergy-core Wiki
Tarvittavien pakettien asennus onnistui ja QT Creator 4.14.1 starttaa nätisti, mutta ohjeessa kohta "Edit the Qt kit "Environment" field under Tools -> Options -> Build & Run -> Kits and add BOOST_ROOT=/home/<user>/boost" aiheuttaa kysymysmerkkejä, kun en löydä tuolta Creatorista oikein paikkaa minne tuo pitäisi lisätä.
Polun seuraaminen onnistuu tuonne Tools -> Options asti ja sitten tökkää kun Build & Run alta ei löydy Kits -kohtaa, eikä myöskään Enviroment-kenttää. Enviroment ja Kits -ovat omia valintojaan vasemmassa reunassa, mutta niiden alta en myöskään löydä mitään järkevää paikka, minne tuo "BOOST_ROOT=/home/<user>/boost" voisi sijoittaa.
Eli mihin tuo oikein lisätään?
Putkiaivot sanoo, että tuolla muuttujalla on jotain merkitystä kääntämisessä...Jos tarkoitus on vaan kääntää se niin mikset seuraa sitä ohjesivun lopussa olevaa kohtaa, CLI ja Linux? Ei tarvitse minkään vieraan IDEn kanssa värkätä.
#pragma once
#include <fstream>
#include <iostream>
#include "mittaus.h"
namespace Project1 {
using namespace System;
using namespace System::IO::Ports;
public ref class MyForm : public System::Windows::Forms::Form
{
public:
MyForm(void)
{
InitializeComponent();
findPorts();
}
protected:
private: System::IO::Ports::SerialPort^ serialPort1;
#pragma region Windows Form Designer generated code
void InitializeComponent(void)
{
this->components = (gcnew System::ComponentModel::Container());
this->serialPort1 = (gcnew System::IO::Ports::SerialPort(this->components));
}
#pragma endregion
private: void findPorts(void)
{
array<Object^>^ objectArray = SerialPort::GetPortNames();
}
private: System::Void button7_Click(System::Object^ sender, System::EventArgs^ e) {
//add sender name
String^ name = this->serialPort1->PortName;
//grab text and store in send buffer
String^ message = "hello";
//write to serial
if (this->serialPort1->IsOpen)
this->serialPort1->WriteLine(message);
else
this->textBox2->Text = "Port Not Opened";
}
Ehdotan että siirrät sarjaportin käsittelyn kokonaan unmanaged-puolelle (mittaus.cpp), jolloin managed c++ / winforms -osastoon jää vain GUI eli ne pari nappia. Tai sitten opiskelet aika paljon lisää. Tai kirjoitat koko homman uudelleen esimerkiksi pythonilla, jolloin neuvojakin löytyy netistä paremmin.Mulla on tässä kotiautomaatiojutussa Visual Studiolla tehty Windows GUI, jossa on toimiva sarjaporttikommunikaatio. Nyt minun pitäisi päästä lukemaan ja kirjoittamaan guissa (MyForm.h) avattua sarjaporttia mittaus.cpp:llä. Onko se mahdollista kun setuppi on tällähetkellä tällainen ja tuolla on noita privateja tms.? Vai pitääkö koittaa kaikki toiminnallisuus sisällyttää tuohon guin MyForm.h:n?
Gui jossa sarjaporttikommunikaatio toimii nyt:
form.h:
Mulle on epäselvää, että miten miten voisin lähettää esim. tuon hello -stringin mittaus.cpp:stä jo valmiiksi avattuun sarjaporttiin. Vai onnistuuko se mitenkään ilman isompaa remonttia?Koodi:#pragma once #include <fstream> #include <iostream> #include "mittaus.h" namespace Project1 { using namespace System; using namespace System::IO::Ports; public ref class MyForm : public System::Windows::Forms::Form { public: MyForm(void) { InitializeComponent(); findPorts(); } protected: private: System::IO::Ports::SerialPort^ serialPort1; #pragma region Windows Form Designer generated code void InitializeComponent(void) { this->components = (gcnew System::ComponentModel::Container()); this->serialPort1 = (gcnew System::IO::Ports::SerialPort(this->components)); } #pragma endregion private: void findPorts(void) { array<Object^>^ objectArray = SerialPort::GetPortNames(); } private: System::Void button7_Click(System::Object^ sender, System::EventArgs^ e) { //add sender name String^ name = this->serialPort1->PortName; //grab text and store in send buffer String^ message = "hello"; //write to serial if (this->serialPort1->IsOpen) this->serialPort1->WriteLine(message); else this->textBox2->Text = "Port Not Opened"; }
Koska kysymyksessä ilmeisesti on harrasteprojekti eikä ensisijaisesti c++-opiskelu, niin toistan ehdotukseni Pythonista. Sillä saa yksinkertaisen tkinter-käyttöliittymän helposti tehtyä, ja sarjaportinkin ohjelmointi on selkeää:^Kiitti. Kerkesin alkaa koittamaan reference funktiokutsulla, mutta en tiedä saanko sillä toimimaan. Mutta opinpahan ehkä jotain uutta. Pitänee sen jälkeen koittaa siirtää sarjaporttihomma kokonaan sinne mittaus.cpp puolelle.
extern int measureValue;
extern std::string measureType;
int main(){
measureValue = 1;
measureType = "testi"
}
int measureValue;
string measureType;
int measure() {
//Täällä kun lukee intin, se on oikein. Mutta kun lukee stringin, se on tyhjä.
}
No ainakin tuolta mainista puuttuu puolipiste stringin perästä. Luulisi kyllä että kääntäjä olisi tuon huomannut.Kiitti. Olen itseasiassa tehnyt tämän saman projektin aiemmin aika pitkälle Pythonilla, mutta nyt kun aloin lisäämään tähän toiminnallisuuksia niin taustalla oli halu myös oppia C++:aa. Pitää seuraavaksi koittaa myös noilla mainitsemillasi kielillä
Mutta taas törmäsin ongelmaan. Saan int arvot liikkumaan tiedostojen välillä, mutta en stringejä.
form.h:
mittaus.cpp:Koodi:extern int measureValue; extern std::string measureType; int main(){ measureValue = 1; measureType = "testi" }
Reference pass to function - systeemi ei tässä oikein toimi, kun funktioita mittaus.cpp:ssä on monia ja enkä haluaisi tehdä jokaiselle funktiolle omaa nappulaa, jolla lähetän stringin. Olisi hyvä, että jokainen funktio voisi lukea stringin samoin kuin lukee intinkin, mutta en oikein ymmärrä miksei extern string toimi samalla tavalla kuin int. Kääntäjä ei valita mitään, mutta string on tyhjä mittaus.cpp:ssä.Koodi:int measureValue; string measureType; int measure() { //Täällä kun lukee intin, se on oikein. Mutta kun lukee stringin, se on tyhjä. }
Hei! Kokeilin tuota koodia seuraavilla täydennyksillä, eli ensin kirjoitan main funktiossa molemmat arvot, tulostan ne tuolla measure funktiossa, ylikirjoitan arvot ja lopuksi tulostan uudelleen main funktion lopussa:Kiitti. Olen itseasiassa tehnyt tämän saman projektin aiemmin aika pitkälle Pythonilla, mutta nyt kun aloin lisäämään tähän toiminnallisuuksia niin taustalla oli halu myös oppia C++:aa. Pitää seuraavaksi koittaa myös noilla mainitsemillasi kielillä
Mutta taas törmäsin ongelmaan. Saan int arvot liikkumaan tiedostojen välillä, mutta en stringejä.
form.h:
mittaus.cpp:Koodi:extern int measureValue; extern std::string measureType; int main(){ measureValue = 1; measureType = "testi" }
Reference pass to function - systeemi ei tässä oikein toimi, kun funktioita mittaus.cpp:ssä on monia ja enkä haluaisi tehdä jokaiselle funktiolle omaa nappulaa, jolla lähetän stringin. Olisi hyvä, että jokainen funktio voisi lukea stringin samoin kuin lukee intinkin, mutta en oikein ymmärrä miksei extern string toimi samalla tavalla kuin int. Kääntäjä ei valita mitään, mutta string on tyhjä mittaus.cpp:ssä.Koodi:int measureValue; string measureType; int measure() { //Täällä kun lukee intin, se on oikein. Mutta kun lukee stringin, se on tyhjä. }
mittaus.h: | mittaus.cpp | main.cpp |
C++:
|
C++:
|
C++:
|
$ g++ main.cpp mittaus.cpp
$ ./a.out
1testi
2onnistui
mittaus.h | mittaus.cpp | main.cpp |
C++:
|
C++:
|
C++:
|
$ g++ main.cpp mittaus.cpp
$ ./a.out
1
2testi
enum measureType { temperature, speed, brightness };
Veikkaan, että pitäs laittaa tänne:Yritän kääntää Synergyä Ubuntu 21.10:lle seuraamalla näitä ohjeita: Compiling · symless/synergy-core Wiki
Tarvittavien pakettien asennus onnistui ja QT Creator 4.14.1 starttaa nätisti, mutta ohjeessa kohta "Edit the Qt kit "Environment" field under Tools -> Options -> Build & Run -> Kits and add BOOST_ROOT=/home/<user>/boost" aiheuttaa kysymysmerkkejä, kun en löydä tuolta Creatorista oikein paikkaa minne tuo pitäisi lisätä.
Polun seuraaminen onnistuu tuonne Tools -> Options asti ja sitten tökkää kun Build & Run alta ei löydy Kits -kohtaa, eikä myöskään Enviroment-kenttää. Enviroment ja Kits -ovat omia valintojaan vasemmassa reunassa, mutta niiden alta en myöskään löydä mitään järkevää paikka, minne tuo "BOOST_ROOT=/home/<user>/boost" voisi sijoittaa.
Eli mihin tuo oikein lisätään?
Kiitti ystävällisestä ja perusteellisesta vastauksesta Olin tehnyt koodiin mokan, jolle olin jostain syystä täysin sokea. En osannut kopioida sitä edes tuohon ongelmakuvaukseen. Eli alustin tuon stringin vielä toistamiseen ja tässä taitaa extern nollautua:Hei! Kokeilin tuota koodia seuraavilla täydennyksillä, eli ...
extern int measureValue;
extern std::string measureType;
int main(){
measureValue = 1;
std::string measureType = "testi"; //eli "std::string" oli tässä liikaa :)
}
Tarkalleenottaen tuossa ei externiin kosketa lainkaan, sen sijaan määritellään main-funktioon uusi muuttuja samalla nimellä ja alustetaan se. Tämä on näkyvissä ainoastaan tuon funktion scopessa.Kiitti ystävällisestä ja perusteellisesta vastauksesta Olin tehnyt koodiin mokan, jolle olin jostain syystä täysin sokea. En osannut kopioida sitä edes tuohon ongelmakuvaukseen. Eli alustin tuon stringin vielä toistamiseen ja tässä taitaa extern nollautua:
Koodi:extern int measureValue; extern std::string measureType; int main(){ measureValue = 1; std::string measureType = "testi"; //eli "std::string" oli tässä liikaa :) }
Yrität turhan vaikeasti. Et tarvitse looppia, vaan pelkän joinin:Uskoakseni vika on join-methodin käytössä.
hobbies = ["golf", "slalom", "keppihevostelu"]
print(", ".join(hobbies))
Mielestäni annoin sen vastauksen jo Eli ota tuo for-luuppi kokonaan pois. Et tarvitse sitä, et mitään hobby_list-muuttujaa.. Ja sulla taitaa olla normi- ja aaltosulkeet väärinpäin. Eli normisulkeet sun pitää printata, älä laita niitä aaltosulkeiden sisään. Aaltosulkeiden sisällä oleva interpoloidaan. Öbaut näin (en testannut):Ongelmana on että tulostus tapahtuu seuraavasti tällä erää:
Peter Pythons 27 years codingknitting kun tavoite olisi Peter Pythons 27 years (coding, knitting).
...
hobbies = ", ".join(person["hobbies"])
print(f"{name} {age} years ({hobbies})")
import json
def print_persons(filename: str):
with open(filename) as new_file:
data = new_file.read()
persons = json.loads(data)
for person in persons:
name = person["name"]
age = person["age"]
hobbies = person["hobbies"]
hobby_list = " "
for hobby in hobbies:
hobby_list += hobby
print(f"{name} {age} years {(hobby_list)}")
print(', '.join(hobbies))
Meniskö tällä.Osaisikohan joku auttaa regexin kanssa?
Minulla on stringejä, jotka on suurinpiirtein tämän näköisiä:
"AAA111:Ford BBB-111:Volvo CCC-111:Naapurin auto"
Haluaisin saada tuosta siis nämä auton rekisterinumeroilta näyttävät stringit: "AAA111", "BBB-111", "CCC-111"
Eli siis kaikki teksti välilyönnin ja ":" merkin välillä. Lisäksi kaikki ennen ensimmäistä ":" merkkiä. "Rekisterinumeron" formaatti ja pituus on vapaa, mutta se ei voi sisältää merkkiä ":" tai välilyönti.
PHP on ohjelmointikieli, eli pitäisi sitä tukeva regex olla.
$s = "AAA111:Ford BBB-111:Volvo CCC-111:Naapurin auto";
preg_match_all("/[A-Z]{3}-?\d{3}/", $s, $m);
var_dump($m);
Näin nyt ainakin, $matches[2] sisältää rekkaritOsaisikohan joku auttaa regexin kanssa?
Minulla on stringejä, jotka on suurinpiirtein tämän näköisiä:
"AAA111:Ford BBB-111:Volvo CCC-111:Naapurin auto"
Haluaisin saada tuosta siis nämä auton rekisterinumeroilta näyttävät stringit: "AAA111", "BBB-111", "CCC-111"
Eli siis kaikki teksti välilyönnin ja ":" merkin välillä. Lisäksi kaikki ennen ensimmäistä ":" merkkiä. "Rekisterinumeron" formaatti ja pituus on vapaa, mutta se ei voi sisältää merkkiä ":" tai välilyönti.
PHP on ohjelmointikieli, eli pitäisi sitä tukeva regex olla.
preg_match_all("/(([^:\s]+):)+/", "AAA111:Ford BBB-111:Volvo CCC-111:Naapurin auto", $matches);
Kiitos, tämä on tarpeeksi lähellä.Näin nyt ainakin, $matches[2] sisältää rekkarit
PHP:preg_match_all("/(([^:\s]+):)+/", "AAA111:Ford BBB-111:Volvo CCC-111:Naapurin auto", $matches);
{
a: 1,
b: "foo",
c: { d: "bar", e: { f: 42}}
}
Ja pitäisi käydä tuo läpi. Periaatteessa pitäisi olla simppeli rekursio, mutta internet ei suostu paljastamaan oikeaa tapaa huomata, milloin arvo onkin toinen Mappi.
const queryParams = (params, prefix = "") => {
let retval: string[] = [];
if (params) {
if (prefix !== "") {
prefix = prefix + '_';
}
Object.keys(params).map(k => {
if (typeof params[k] === "object" && params[k] !== null) {
queryParams(params[k], prefix + k).map(value => retval.push(value));
} else {
retval.push(prefix + encodeURIComponent(k) + "=" + encodeURIComponent(params[k]));
}
})
}
return retval;
}
const [lazyParams, setLazyParams]: [DataTablePFSEvent, (lazyParams: DataTablePFSEvent) => void] = React.useState<DataTablePFSEvent>({
first: 0,
rows: 50,
page: 0,
sortField: "name",
sortOrder: 1,
multiSortMeta: null,
filters: {
global: { value: null, matchMode: FilterMatchMode.CONTAINS },
name: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }] },
dob: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.EQUALS }] },
dod: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.EQUALS }] },
nationality: { value: null, matchMode: FilterMatchMode.EQUALS },
work_count: { value: null, matchMode: FilterMatchMode.EQUALS },
story_count: { value: null, matchMode: FilterMatchMode.EQUALS },
roles: { value: null, matchMode: FilterMatchMode.EQUALS }
}
});
first=0&rows=50&sortField=name&sortOrder=1&filters_global_value=null&filters_global_matchMode=contains&filters_name_operator=and&filters_name_constraints_0_value=null&filters_name_constraints_0_matchMode=startsWith&filters_dob_operator=and&filters_dob_constraints_0_value=null&filters_dob_constraints_0_matchMode=equals&filters_dod_operator=and&filters_dod_constraints_0_value=null&filters_dod_constraints_0_matchMode=equals&filters_nationality_value=null&filters_nationality_matchMode=equals&filters_work_count_value=null&filters_work_count_matchMode=equals&filters_story_count_value=null&filters_story_count_matchMode=equals&filters_roles_value=null&filters_roles_matchMode=equals&page=0&pageCount=101
En tiedä typescriptistä mutta olisko koska tuossa kutsu funktiolle sekä parametrilla params että rekursiivisesti params[k], tyyppiä on vaikea päätellä.Saakohan seuraavan funktion params-parametrin tyypistä tulevaa valitusta (implisiittisesti any) pois?
Implicit any -varoitus tulee lintteriltä kun et anna mitään tyyppiä ja kääntäjä olettaa silloin tyypiksi any:n. Mutta jos tuo funktio syö ihan minkä tahansa objektin sisään (kuten jotkut funktiot syövät), niin oikea tapa on silloin eksplisiittisesti antaa se tyyppi, eli esim. (params: Object, prefix = ""). Tai jos se syö ihan mitä tahansa, niin sitten annat tyypiksi any:n, eksplisiittisesti.Kokeilin tuota. Siis TS:ssä voi kyllä antaa useamman eri tyypin vaihtoehdoksi, mutta en saanut tuota toimimaan millään määrittelyillä. Ilman tyyppiä tuo siis toimii vaikka editori tuosta valittaakin.