some1 Δημοσ. 7 Φεβρουαρίου 2013 Μέλος Δημοσ. 7 Φεβρουαρίου 2013 Thank you both! Θα δοκιμάσω και θα ενημερώσω!!!
albNik Δημοσ. 7 Φεβρουαρίου 2013 Δημοσ. 7 Φεβρουαρίου 2013 παπι γιατί τα προσθέτεις? επίσης αυτό string gr = "1.000"; string us = "1,000"; βγάζει 1001 (αντί για 2 η 2000)
παπι Δημοσ. 7 Φεβρουαρίου 2013 Δημοσ. 7 Φεβρουαρίου 2013 παπι γιατί τα προσθέτεις? Για ελεγχο επίσης αυτό string gr = "1.000"; string us = "1,000"; βγάζει 1001 (αντί για 2 η 2000) αυτο δεν μπορεις να το δεις ουτε με regex. Ουτε με το ματι
Apoll Δημοσ. 7 Φεβρουαρίου 2013 Δημοσ. 7 Φεβρουαρίου 2013 Χρησιμοποίησε CultureInfo("en-US"). Δύο γραμμές κώδικας είναι όλη η μετρατροπή (και πέρνεις currency, αριθμό, ό,τι γουστάρεις με την ίδια εντολή επίσης)
some1 Δημοσ. 7 Φεβρουαρίου 2013 Μέλος Δημοσ. 7 Φεβρουαρίου 2013 Χρησιμοποίησε CultureInfo("en-US"). Δύο γραμμές κώδικας είναι όλη η μετρατροπή (και πέρνεις currency, αριθμό, ό,τι γουστάρεις με την ίδια εντολή επίσης) Με ενδιαφέρει το παραπάνω! Έστω η μεταβλητή μας string amount που περιέχει την τιμή 1,345.98 ή 3.690,14. Πως ζητάω την μετατροπή;
albNik Δημοσ. 7 Φεβρουαρίου 2013 Δημοσ. 7 Φεβρουαρίου 2013 Αν έχει και "." και "," συγκρίνεις amount.IndexOf('.') και amount.IndexOf(',') για να αποφασίσεις αν είναι el-GR ή en-US. Aλλιώς δεν έιναι δυο γραμμές κώδικα
defacer Δημοσ. 7 Φεβρουαρίου 2013 Δημοσ. 7 Φεβρουαρίου 2013 Τωρα που λειπει ο defecer, ας ποσταρω την μακαροναδα μου. Γενικά αυτό που λέει το παπί είναι η σωστή ιδέα. Απλώς καλύτερα είναι να χρησιμοποιήσεις την double.TryParse. Παράδειγμα με sexy αλλά λίγο επικίνδυνη χρήση LINQ: var cultures = new[] { "el-GR", "en-US" }.Select(CultureInfo.GetCultureInfo); var inputs = new[] { "1.000,41", "1,000.41" }; double temp = 0; foreach (var input in inputs) { var d = cultures.Where(c => double.TryParse(input, NumberStyles.Number, c.NumberFormat, out temp)) .Select(c => temp) .Single(); Console.WriteLine("Parsing {0} gives {1}", input, d); } See it in action. Αν η είσοδος είναι εγγυημένα σε κάποιο άγνωστο μεν αλλά σωστό για κάποια από τις cultures που δοκιμάζοντα format δε, αυτό θα δουλέψει. Επειδή όμως η double.Parse δέχεται και όχι τόσο σωστά strings (π.χ. θα παρσάρει και το "1,00041" όπου το κόμμα διαχωρίζει κανονικά ψηφία και όχι δεκαδικά) υπάρχει περίπτωση να παρσάρεται και από τα 2 cultures οπότε α) θα φας exception από το .Single() και β) πρέπει να βρεις ποιό είναι το σωστό parse. Με την επιστημονική μέθοδο "έτσι μου φάνηκε" το σωστό parse σ' αυτές τις περιπτώσεις είναι εκείνο όπου παίρνεις το διαχωριστή σαν δεκαδικό, άρα έχει σαν αποτέλεσμα το νούμερο που είναι πιο κοντά στο μηδέν (όχι το μικρότερο γιατί μπορεί να μιλάμε για αρνητικούς αριθμούς). Επομένως αλλάζεις το .Single() σε: var cultures = new[] { "el-GR", "en-US" }.Select(CultureInfo.GetCultureInfo); var inputs = new[] { "1.000,41", "1,000.41", "1,000,41", "1,00041", "-1,00041", "1.00.41" }; double temp = 0; foreach (var input in inputs) { var d = cultures.Where(c => double.TryParse(input, NumberStyles.Number, c.NumberFormat, out temp)) .Select(c => temp) .OrderBy(Math.Abs) .First(); Console.WriteLine("Parsing {0} gives {1}", input, d); } See it in action.
warlock9_0 Δημοσ. 7 Φεβρουαρίου 2013 Δημοσ. 7 Φεβρουαρίου 2013 μπακαλίστικη σκέψη σε string, τα κάνεις όλα τελείες και κρατάς μόνο την τελευταία
Apoll Δημοσ. 7 Φεβρουαρίου 2013 Δημοσ. 7 Φεβρουαρίου 2013 Γενικά αυτό που λέει το παπί είναι η σωστή ιδέα. Απλώς καλύτερα είναι να χρησιμοποιήσεις την double.TryParse. Παράδειγμα με sexy αλλά λίγο επικίνδυνη χρήση LINQ: var cultures = new[] { "el-GR", "en-US" }.Select(CultureInfo.GetCultureInfo); var inputs = new[] { "1.000,41", "1,000.41" }; double temp = 0; foreach (var input in inputs) { var d = cultures.Where(c => double.TryParse(input, NumberStyles.Number, c.NumberFormat, out temp)) .Select(c => temp) .Single(); Console.WriteLine("Parsing {0} gives {1}", input, d); } See it in action. Αν η είσοδος είναι εγγυημένα σε κάποιο άγνωστο μεν αλλά σωστό για κάποια από τις cultures που δοκιμάζοντα format δε, αυτό θα δουλέψει. Επειδή όμως η double.Parse δέχεται και όχι τόσο σωστά strings (π.χ. θα παρσάρει και το "1,00041" όπου το κόμμα διαχωρίζει κανονικά ψηφία και όχι δεκαδικά) υπάρχει περίπτωση να παρσάρεται και από τα 2 cultures οπότε α) θα φας exception από το .Single() και β) πρέπει να βρεις ποιό είναι το σωστό parse. Με την επιστημονική μέθοδο "έτσι μου φάνηκε" το σωστό parse σ' αυτές τις περιπτώσεις είναι εκείνο όπου παίρνεις το διαχωριστή σαν δεκαδικό, άρα έχει σαν αποτέλεσμα το νούμερο που είναι πιο κοντά στο μηδέν (όχι το μικρότερο γιατί μπορεί να μιλάμε για αρνητικούς αριθμούς). Επομένως αλλάζεις το .Single() σε: var cultures = new[] { "el-GR", "en-US" }.Select(CultureInfo.GetCultureInfo); var inputs = new[] { "1.000,41", "1,000.41", "1,000,41", "1,00041", "-1,00041", "1.00.41" }; double temp = 0; foreach (var input in inputs) { var d = cultures.Where(c => double.TryParse(input, NumberStyles.Number, c.NumberFormat, out temp)) .Select(c => temp) .OrderBy(Math.Abs) .First(); Console.WriteLine("Parsing {0} gives {1}", input, d); } See it in action. Γιατί double και όχι decimal; Λίγη οικονομία όταν γράφουμε δεν βλάπτει Αν σίγουρα κάποιος θα γράψει είτε #,###.## ή #.###,## και όχι κάποιο από τα άλλα cultures τότε στα γρήγορα ένα παράδειγμα : Σε VB.NET Dim defaultCulture As CultureInfo = Thread.CurrentThread.CurrentCulture Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US") If Decimal.TryParse(numberToChange, decValue) Then ConvertedValue = Convert.ToDecimal(numberToChange).ToString(Specifier, New CultureInfo("en-US")) Else Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("el-GR") ConvertedValue = Convert.ToDecimal(numberToChange).ToString(Specifier, New CultureInfo("en-US")) Thread.CurrentThread.CurrentCulture = defaultCulture End If ' Specifier είναι string με G = number, c = currency, p = percentage κ.α. Σε C#.NETCultureInfo defaultCulture = Thread.CurrentThread.CurrentCulture; Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US"); if (decimal.TryParse(numberToChange, out decValue)) { ConvertedValue = Convert.ToDecimal(numberToChange).ToString(Specifier, new CultureInfo("en-US")); } else { Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("el-GR"); ConvertedValue = Convert.ToDecimal(numberToChange).ToString(Specifier, new CultureInfo("en-US")); Thread.CurrentThread.CurrentCulture = defaultCulture; }
albNik Δημοσ. 7 Φεβρουαρίου 2013 Δημοσ. 7 Φεβρουαρίου 2013 μπακαλίστικη σκέψη σε string, τα κάνεις όλα τελείες και κρατάς μόνο την τελευταία Μόνο την τελευταία αν είναι το πολύ 2 χαρακτήρες από το τέλος. Οι λυσεις με CultureInfo δεν δουλεύουν όταν πετύχει η Parse και σε US και σε Gr και δώσει διαφορετικά αποτελέσματα. Ποιο θα είναι το σωστο μετά?
some1 Δημοσ. 7 Φεβρουαρίου 2013 Μέλος Δημοσ. 7 Φεβρουαρίου 2013 Βασικά το μόνο σίγουρο σε αυτά τα νούμερα είναι πως θα έχουν το σημείο "." ή "," στην 3η θέση από δεξιά, δηλαδή εμφανίζονται πάντα 2 δεκαδικά ψηφία.. Δεν είμαστε σίγουροι οτι θα έχουμε πάντα την χιλιάδα. Δηλαδή ###,## ή ##.##. Αν μπορέσουμε να μετρήσουμε την θέση του "," ή της τελείας "." από δεξιά προς αριστερά, θα μπορούμε να συμπεράνουμε με ακρίβεια σε ποιό locale είναι. Ίσως αυτή είναι η πιο απλή λύση, αλλά η IndexOf μετράει αριστερά προς δεξιά
albNik Δημοσ. 7 Φεβρουαρίου 2013 Δημοσ. 7 Φεβρουαρίου 2013 ammount.Length-IndexOf() Υπάρχει και η LastIndexOf()
some1 Δημοσ. 7 Φεβρουαρίου 2013 Μέλος Δημοσ. 7 Φεβρουαρίου 2013 Η LastIndexOf δεν μετράει από δεξιά προς αριστερά, απλώς επιστρέφει την θέση της τελευταίας εμφάνισης του χαρακτήρα..!?
some1 Δημοσ. 7 Φεβρουαρίου 2013 Μέλος Δημοσ. 7 Φεβρουαρίου 2013 ναι αλλά εγώ θέλω να ξέρω αν το "," ή η "." είναι στην 3η θέση από το τέλος. Και δεν μπορώ να του πω ψάξε να το βρείς τόσες θέσεις από την αρχή (από αριστερά προς δεξιά δηλαδή) διότι μπορεί να έχω χιλιάδα, μπορεί και όχι. Είπα λίγο πριν (δεν το διευκρίνησα σωστά στο 1ο post, αφού θεώρησα το μέγιστο μήκος ως περιορισμό) πως το ποσό μπορεί να είναι είτε #.###,##, είτε ###,##, είτε ##,##. Άρα μόνο ο έλεγχος από δεξιά προς αριστ. μας βοηθάει.. edit: Έχω δημιουργήσει ένα μικρό "χάος" με τις κατευθύνσεις που έχω δώσει, αλλά νομίζω! το πιο απλό και αποτελεσματικό θα είναι το παραπάνω, να βρίσκουμε δηλαδή το σύμβολο στην 3η θέση από το τέλος.
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα