2012-01-27 20 views
7

मैं कैसे जांच सकता हूं कि एक स्ट्रिंग लंबे, एक डबल, या सिर्फ एक नियमित स्ट्रिंग का प्रतिनिधित्व करती है या नहीं? मुझे ऐसा करने की ज़रूरत है क्योंकि इस मान को उसके प्रकार के अनुसार डेटाबेस में अनुक्रमित करने की आवश्यकता है। वर्तमान में मैं स्ट्रिंग को पार्स करने और अपवादों की जांच करने की कोशिश कर रहा हूं लेकिन चूंकि कोड को अक्सर बुलाया जाता है, इसलिए मुझे आश्चर्य है कि ऐसा करने का एक और अधिक प्रभावी तरीका है या नहीं। मेरे कोड वर्तमान में इस तरह दिखता है:कैसे जांचें कि स्ट्रिंग किस प्रकार और किस प्रकार की संख्या का प्रतिनिधित्व करती है?

String value = ...; 
// For example, could be "213678", "654.1236781", or "qwerty12345" 

try { 
    Long longValue = Long.parseLong(value); 
    // Index 'longValue' in the database 
} catch (NumberFormatException parseLongException) { 
    try { 
     Double doubleValue = Double.parseDouble(value); 
     // Index 'doubleValue' in the database 
    } catch (NumberFormatException parseDoubleException) { 
     // Index 'value' in the database 
    } 
} 

संपादित करें:

मैं सिर्फ @ user949300 के सुझाव regex पैटर्न का उपयोग करने के प्रति के रूप में एक त्वरित बेंचमार्किंग व्यायाम किया था और यह ऊपर अपवाद हैंडलिंग कोड की तुलना में थोड़ा बेहतर प्रदर्शन किया। यहाँ किसी और मामले में किसी को कोड यह उपयोगी पाता है:

Pattern longPattern = Pattern.compile("^[-+]?[0-9]+$"); 
Pattern doublePattern = Pattern.compile("^[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?$"); 

// Check for long regex pattern before the double regex pattern 
// since the former is a strict subset of the latter 
if (longPattern.matcher(value).matches()) { 
    // Perform indexing for long in the database 
} else if (doublePattern.matcher(value).matches()) { 
    // Perform indexing for double in the database 
} else { 
    // Perform indexing for string in the database 
} 

यहाँ 50,000 प्रविष्टियों जहां प्रकार की अनुमानित टूटने 50% देशांतर है, 10% युगल, 40% तार जाँच (कार्यभार के प्रतिनिधि के लिए बेंच मार्किंग परिणाम हैं अपने आवेदन प्रक्रियाओं) कि:

--- Exception handling code --- 
STRING - actual: 19861, found: 19861 
DOUBLE - actual: 4942, found: 4942 
LONG - actual: 25197, found: 25197 
Time taken: 2561 ms 

--- Regex pattern matching code --- 
STRING - actual: 19861, found: 19861 
DOUBLE - actual: 4942, found: 4942 
LONG - actual: 25197, found: 25197 
Time taken: 1565 ms 
+0

आप 'जावा 7' उपयोग कर रहे हैं की तुलना में ([बहु पकड़ने के ब्लॉक के लिए अपवाद] पर एक नज़र http://extreme-java.blogspot.com/2011/05/jdk-7 ले -multi-catch-block-for-upss.html) – RanRag

+0

@RanRag मुझे नहीं लगता कि इस स्थिति में बहु-पकड़-ब्लॉक कितने उपयोगी हैं। दूसरा पकड़ अंदर है - बाद में नहीं - पहला पकड़ ब्लॉक। – emory

+0

आप सही हैं मैंने इसे नहीं देखा है। – RanRag

उत्तर

3

क्या आपने नियमित अभिव्यक्तियों पर विचार किया है?

यदि स्ट्रिंग में कुछ भी है (शुरुआत में), और 0-9 या।, यह एक स्ट्रिंग है। (नोट - यह अंतर्राष्ट्रीयकरण और वैज्ञानिक नोटेशन को अनदेखा करता है - क्या वे समस्याएं हैं?)

अन्यथा, इसमें एक है।, यह एक डबल है। (ठीक है, आपको केवल एक ही परीक्षण करना चाहिए।, लेकिन यह एक शुरुआत है)

अन्यथा, यह एक लंबा है।

परावर्तक से बाहर, मैं अभी भी अपवादों की जांच कर सकता हूं, लेकिन यह एक तेज़ तरीका हो सकता है।

नोट जोड़ा गया है कि मुझे लगता है कि रेगेक्स का परीक्षण विभिन्न पार्स रूटीन से अपवाद फेंकने से तेज है, लेकिन यह वास्तव में सच नहीं हो सकता है। आपको कुछ परीक्षण करना चाहिए।

+0

मैं इस धारणा के तहत था कि रेगेक्स धीमा हो जाएगा, लेकिन एक त्वरित बेंचमार्किंग अभ्यास किया गया जो रेगेक्स पैटर्न का उपयोग करके लंबे समय तक और युगल से मेल खाता है और यह थोड़ा तेज़ हो जाता है। मैंने इस कोड को बेंचमार्किंग परिणामों के साथ अपने प्रश्न में जोड़ा है। – Dawood

+0

एक अच्छा बेंचमार्क करने के लिए धन्यवाद। – user949300

2

जहाँ तक मुझे पता है कि वहाँ के रूप में की तुलना में इस अन्य करने के लिए कोई सुरुचिपूर्ण तरीका है। मैं अनुशंसा करता हूं कि आप उन्हें कम से कम आम के क्रम में पार्स करें ताकि इसे जितनी जल्दी हो सके।

यदि आपके पास 3 से अधिक संभावित प्रकार हैं तो आपको गहरा और बदसूरत try-catch घोंसला होगा, लेकिन तकनीकी रूप से यह तेज होगा यदि आपने प्रत्येक पार्स प्रयास को अपनी विधि में तोड़ दिया है; यहां ट्रेडऑफ यह है कि क्या आप कोड स्पष्टता या तेज़ी से निष्पादन चाहते हैं - ऐसा लगता है जैसे आप बाद वाले को चाहते हैं।

+0

यदि मैं आपको सही ढंग से समझता हूं, तो घटना आवृत्ति के क्रम में पार्सिंग काम नहीं करेगा ** स्ट्रिंग ** प्रस्तुतियां ** डबल ** का सख्त सुपरसैट होगा, जो बदले में ** लांग * *। यदि कोई मान लंबा होना चाहिए, तो यह अभी भी अपवाद उठाए बिना डबल के रूप में सफलतापूर्वक विश्लेषण करेगा। – Dawood

+0

@ दाऊद: आप सही हैं। मेरा मुद्दा यह है कि उस क्रम को विचार दिया जाना चाहिए जिसमें आप पार्सिंग कर रहे हैं ताकि आप कुछ काम से बच सकें (उम्मीद है)। –

1

आप कुछ सुधार प्राप्त करने में सक्षम हो सकते हैं (विशेष रूप से यदि आप वैज्ञानिक नोटेशन जैसे 1e12 पर शासन कर सकते हैं) तो लंबे समय से पता लगाने के लिए गैर-अंकों की जांच कर सकते हैं। एक सामान्य विधि है कि एक सा तेजी से किसी भी संख्या के आधार में काम करता है, तो एक दशमलव-एकमात्र तरीका हो सकता है के लिए

Long.parseLong() प्रतिनिधियों।

शून्य से संकेत याद रखें, अगर इन आपके डेटा में संभव हो रहे हैं ...

डबल्स हैं कठिन है क्योंकि 654.1236871 मान्य है, लेकिन 654.12.36.87...1, नहीं है हालांकि वे पात्रों के एक ही सेट होते हैं। तो पूर्ण पार्सिंग शायद की जरूरत है।

1

आपका कोड अच्छा दिखता है।

कुछ रूपरेखा, और उस पर आधारित है, तो आप अपने कोड बहुत धीमी गति से मिल जाए, तो आप संभावित अनुकूलन (सरल पाश की तरह है, तो सभी वर्णों में अंक को देखने के लिए) के बारे में सोच सकते हैं।

रूपरेखा से पहले अपने कोड का अनुकूलन करने की कोशिश मत करो। खासकर जावा जैसी भाषाओं में।

1

एक संभावना यह java.io.StreamTokenizer है:

Reader r = new StringReader(value); 
StreamTokenizer st = new StreamTokenizer(r); 
int tokenType = st.nextToken(); 
double number; 
String word; 
switch (tokenType) { 
    case StreamTokenizer.TT_NUMBER: // it's a number 
     number = st.nval; break; 
    case StreamTokenizer.TT_WORD: // it's a string 
     word = st.sval; break; 
} 

यह मुश्किल तरह का हालांकि उपयोग करने के लिए हो सकता है।

0

यदि आपको नकारात्मक Longs नकारात्मक होने की चिंता करने की आवश्यकता नहीं है, तो आप अपाचे कॉमन्स लैंग लाइब्रेरी से NumberUtils.isDigits() और NumberUtils.isNumber() का उपयोग कर सकते हैं।

if(NumberUtils.isDidgets(string)){ 
    //Index long 
} else if(NumberUtils.isNumber(string)){ 
    //Index double 
} else { 
    //Index string 
} 
संबंधित मुद्दे