গো-এ খালি স্ট্রিংয়ের জন্য পরীক্ষার সর্বোত্তম উপায় কোনটি?


260

খালি খালি স্ট্রিং (গো তে) পরীক্ষা করার জন্য কোন পদ্ধতিটি সেরা (আরও মূর্তিমানিক)?

if len(mystring) > 0 { }

বা:

if mystring != "" { }

অথবা অন্য কিছু?

উত্তর:


388

উভয় স্টাইল গো স্ট্যান্ডার্ড লাইব্রেরিতে ব্যবহার করা হয়।

if len(s) > 0 { ... }

strconvপ্যাকেজে পাওয়া যাবে : http://golang.org/src/pkg/strconv/atoi.go

if s != "" { ... }

encoding/jsonপ্যাকেজে পাওয়া যাবে : http://golang.org/src/pkg/encoding/json/encode.go

উভয়ই মূর্খবাদী এবং যথেষ্ট পরিষ্কার। এটি ব্যক্তিগত স্বাদ এবং স্পষ্টতা সম্পর্কিত বিষয়।

রাশ কক্স একটি গোলং-বাদামের থ্রেডে লিখেছেন :

কোডটি পরিষ্কার করে তোলে one
যদি আমি এক্স উপাদানটি দেখতে যাচ্ছি তবে আমি সাধারণত
লেন (গুলি)> x লিখি এমনকি x == 0 এর জন্যও লিখি তবে আমি যদি "যত্নশীল
" তবে এই নির্দিষ্ট স্ট্রিংটি "আমি s ==" "লেখার ঝোঁক রাখি।"

এটি ধরে নেওয়া যুক্তিযুক্ত যে একটি পরিপক্ক সংকলক
লেন (গুলি) == 0 এবং s == "" একই, কার্যকর কোডে সংকলন করবে ।
...

কোডটি পরিষ্কার করুন।

টিএমএমএম এর উত্তরে নির্দেশিত হিসাবে , গো সংকলক উভয় ক্ষেত্রে অভিন্ন কোড তৈরি করে।


1
আমি এই উত্তরের সাথে একমত নই। কেবলমাত্র if mystring != "" { }আজ, সেরা, পছন্দসই এবং প্রতিচ্ছবিযুক্ত উপায়। স্ট্যান্ডার্ড লাইব্রেরিতে অন্যথায় থাকার কারণটি এটি ২০১০ এর আগে লেখা হয়েছিল যখন len(mystring) == 0অপ্টিমাইজেশনের অর্থ হয়েছিল।
Honzajde

12
@ হোনজাজেদে আপনার বক্তব্যটি যাচাই করার চেষ্টা করেছেন, কিন্তু lenখালি / খালি খালি স্ট্রিংগুলি পরীক্ষা করে 1 বছরের কম বয়সী স্ট্যান্ডার্ড লাইব্রেরিতে কমিটস পাওয়া গেছে । ব্র্যাড ফিটজপ্যাট্রিকের এই প্রতিশ্রুতি পছন্দ করুন । আমি আশঙ্কা করছি এটি এখনও স্বাদ এবং স্পষ্টতার বিষয়;)
এএনিসাস

6
@ হোনজ্জাদে ট্রোলিং হচ্ছে না প্রতিশ্রুতিবদ্ধ 3 টি লেন কীওয়ার্ড আছে। আমি h2_bundle.go (লাইন 2702) len(v) > 0এ উল্লেখ করছি । এটি golang.org/x/net/http2 থেকে উত্পন্ন হওয়ায় এটি স্বয়ংক্রিয়ভাবে প্রদর্শিত হয় না, আমি বিশ্বাস করি।
এ্যানিসাস

2
যদি এটি ভিন্ন হয় তবে এটি নতুন নয়। আপনি কেন সরাসরি লিঙ্ক পোস্ট করবেন না? যাইহোক। আমার জন্য যথেষ্ট গোয়েন্দা কাজ ... আমি এটি দেখতে পাচ্ছি না।
honzajde

6
@ হোনজাদে কোন উদ্বেগ নেই আমি ধরে নিয়েছি অন্যরা কীভাবে h2_bundle.go ফাইলের জন্য "লোড ডিফ" ক্লিক করতে হবে তা জানবে।
আনিসাস 16'17

30

এটি অকাল মাইক্রোপটিমাইজেশন বলে মনে হচ্ছে। সংকলক উভয় ক্ষেত্রে বা কমপক্ষে এই দুটিয়ের জন্য একই কোড তৈরি করতে বিনামূল্যে

if len(s) != 0 { ... }

এবং

if s != "" { ... }

কারণ শব্দার্থবিজ্ঞান স্পষ্টভাবে সমান।


1
তবে সম্মত হয়েছে, এটি সত্যই স্ট্রিংয়ের প্রয়োগের উপর নির্ভর করে ... যদি স্ট্রিংগুলি পাস্কলের মতো প্রয়োগ করা হয় তবে লেন (গুলি) ও (1) এ কার্যকর করা হয় এবং যদি সিটির মতো হয় তবে এটি ও (এন)। বা যাই হোক না কেন, যেহেতু লেন () এর সমাপ্তি পর্যন্ত কার্যকর করতে হয়।
রিচার্ড

সংকলকটি এর প্রত্যাশা করে কিনা আপনি কি কোড প্রজন্মের দিকে নজর রেখেছেন বা আপনি কেবল পরামর্শ দিচ্ছেন যে কোনও সংকলক এটি প্রয়োগ করতে পারে?
মাইকেল ল্যাবে

19

দৈর্ঘ্যের জন্য পরীক্ষা করা ভাল উত্তর, তবে আপনি "খালি" স্ট্রিংয়ের জন্যও অ্যাকাউন্ট করতে পারেন যা কেবল শ্বেত স্পেস। "প্রযুক্তিগতভাবে" খালি নয়, তবে যদি আপনি এটি পরীক্ষা করে দেখেন:

package main

import (
  "fmt"
  "strings"
)

func main() {
  stringOne := "merpflakes"
  stringTwo := "   "
  stringThree := ""

  if len(strings.TrimSpace(stringOne)) == 0 {
    fmt.Println("String is empty!")
  }

  if len(strings.TrimSpace(stringTwo)) == 0 {
    fmt.Println("String two is empty!")
  }

  if len(stringTwo) == 0 {
    fmt.Println("String two is still empty!")
  }

  if len(strings.TrimSpace(stringThree)) == 0 {
    fmt.Println("String three is empty!")
  }
}

TrimSpaceমূল স্ট্রিং থেকে একটি নতুন স্ট্রিং বরাদ্দ এবং অনুলিপি করবে, সুতরাং এই পদ্ধতির স্কেল অদক্ষতা প্রবর্তন করবে।
দাই

@ দাই সোর্স কোডটি দেখছেন, এটি কেবল সত্য হবে যদি দেওয়া sটাইপ স্ট্রিংয়ের সাথে s[0:i]একটি নতুন অনুলিপি প্রদান করে। স্ট্রিংগুলি গোতে পরিবর্তনযোগ্য, তাই এখানে কি একটি অনুলিপি তৈরি করা দরকার?
মাইকেল পাসোল্ড

@ মিশেলপ্যাসোল্ড রাইট - strings.TrimSpace( s )স্ট্রিংটি ছাঁটাইয়ের প্রয়োজন না হলে নতুন স্ট্রিং বরাদ্দ এবং চরিত্রের অনুলিপি তৈরি করবে না, তবে যদি স্ট্রিংটি ছাঁটাইয়ের প্রয়োজন হয় তবে অতিরিক্ত অনুলিপি (হোয়াইটস্পেস অক্ষর ছাড়াই) ডাকা হবে।
দাই

1
"প্রযুক্তিগতভাবে খালি" প্রশ্ন is
রিচার্ড

gocriticLinter ব্যবহার প্রস্তাব দেওয়া strings.TrimSpace(str) == ""দৈর্ঘ্য চেকের পরিবর্তে।
y3sh

12

ধরে নিচ্ছি যে খালি জায়গা এবং সমস্ত নেতৃস্থানীয় এবং অনুসরণকারী শ্বেত স্থানগুলি সরানো উচিত:

import "strings"
if len(strings.TrimSpace(s)) == 0 { ... }

কারণ :
len("") // is 0
len(" ") // one empty space is 1
len(" ") // two empty spaces is 2


2
আপনার এই ধারণা কেন? লোকটি পরিষ্কারভাবে খালি স্ট্রিং সম্পর্কে বলে। আপনি যেভাবে স্ট্রিংয়ে কেবলমাত্র এসকিআই অক্ষর চান তা ধরেই আপনি বলতে পারবেন এবং তারপরে এমন একটি ফাংশন যুক্ত করুন যা সমস্ত অ-এসকিআই অক্ষর মুছে ফেলে।
সালভাদোর ডালি

1
কারণ লেন (""), লেন ("") এবং লেন ("") একই জিনিস নয়। আমি ধরে নিচ্ছিলাম যে তিনি এটি নিশ্চিত করতে চেয়েছিলেন যে তার আগে যেগুলির মধ্যে একটি পরিবর্তনশীল তিনি আরম্ভ করেছিলেন তা এখনও "প্রযুক্তিগতভাবে" খালি রয়েছে।
এডউইনার

এটি আসলে এই পোস্ট থেকে আমার যা প্রয়োজন তা হ'ল। আমার কমপক্ষে 1 টি অ-শ্বেতস্পেস অক্ষর থাকার জন্য ব্যবহারকারী ইনপুটটি দরকার এবং এই ওয়ান-লাইনারটি পরিষ্কার এবং সংক্ষিপ্ত। আমাকে যা করতে হবে তা হল শর্তটি < 1+1 করা
শাদোনিনজা

7

এখন পর্যন্ত, গো সংকলক উভয় ক্ষেত্রে অভিন্ন কোড উত্পন্ন করে, তাই এটি স্বাদের বিষয়। জিসিসিগো বিভিন্ন কোড উত্পন্ন করে তবে খুব কমই কেউ এটিকে ব্যবহার করে তাই আমি সে সম্পর্কে চিন্তা করব না।

https://godbolt.org/z/fib1x1



0

মন্তব্য করতে আরও যোগ করতে

মূলত পারফরম্যান্স টেস্টিং কীভাবে করা যায় about

আমি নিম্নলিখিত কোড দিয়ে পরীক্ষা করেছি:

import (
    "testing"
)

var ss = []string{"Hello", "", "bar", " ", "baz", "ewrqlosakdjhf12934c r39yfashk fjkashkfashds fsdakjh-", "", "123"}

func BenchmarkStringCheckEq(b *testing.B) {
    c := 0
    b.ResetTimer()
    for n := 0; n < b.N; n++ {
            for _, s := range ss {
                    if s == "" {
                            c++
                    }
            }
    } 
    t := 2 * b.N
    if c != t {
            b.Fatalf("did not catch empty strings: %d != %d", c, t)
    }
}
func BenchmarkStringCheckLen(b *testing.B) {
    c := 0
    b.ResetTimer()
    for n := 0; n < b.N; n++ {
            for _, s := range ss { 
                    if len(s) == 0 {
                            c++
                    }
            }
    } 
    t := 2 * b.N
    if c != t {
            b.Fatalf("did not catch empty strings: %d != %d", c, t)
    }
}
func BenchmarkStringCheckLenGt(b *testing.B) {
    c := 0
    b.ResetTimer()
    for n := 0; n < b.N; n++ {
            for _, s := range ss {
                    if len(s) > 0 {
                            c++
                    }
            }
    } 
    t := 6 * b.N
    if c != t {
            b.Fatalf("did not catch empty strings: %d != %d", c, t)
    }
}
func BenchmarkStringCheckNe(b *testing.B) {
    c := 0
    b.ResetTimer()
    for n := 0; n < b.N; n++ {
            for _, s := range ss {
                    if s != "" {
                            c++
                    }
            }
    } 
    t := 6 * b.N
    if c != t {
            b.Fatalf("did not catch empty strings: %d != %d", c, t)
    }
}

এবং ফলাফলগুলি ছিল:

% for a in $(seq 50);do go test -run=^$ -bench=. --benchtime=1s ./...|grep Bench;done | tee -a log
% sort -k 3n log | head -10

BenchmarkStringCheckEq-4        150149937            8.06 ns/op
BenchmarkStringCheckLenGt-4     147926752            8.06 ns/op
BenchmarkStringCheckLenGt-4     148045771            8.06 ns/op
BenchmarkStringCheckNe-4        145506912            8.06 ns/op
BenchmarkStringCheckLen-4       145942450            8.07 ns/op
BenchmarkStringCheckEq-4        146990384            8.08 ns/op
BenchmarkStringCheckLenGt-4     149351529            8.08 ns/op
BenchmarkStringCheckNe-4        148212032            8.08 ns/op
BenchmarkStringCheckEq-4        145122193            8.09 ns/op
BenchmarkStringCheckEq-4        146277885            8.09 ns/op

কার্যকরভাবে ভেরিয়েন্টগুলি দ্রুততম সময়ে পৌঁছায় না এবং বৈকল্পিক শীর্ষ গতির মধ্যে কেবলমাত্র ন্যূনতম পার্থক্য (প্রায় 0.01ns / op) থাকে।

এবং আমি যদি সম্পূর্ণ লগ দেখতে পাই তবে চেষ্টাগুলির মধ্যে পার্থক্যটি বেঞ্চমার্ক ফাংশনগুলির মধ্যে পার্থক্যের চেয়ে বেশি।

এছাড়াও বেঞ্চমার্কস্ট্রিংচেকএক এবং বেঞ্চমার্কস্ট্রিংচেকনি বা বেনমার্কস্ট্রিংচেকলেন এবং বেঞ্চমার্কস্ট্রিংচেকলেনগেটের মধ্যে কোনও পরিমাপযোগ্য পার্থক্য রয়েছে বলে মনে হয় না যদিও ল্যাটার্ট ভেরিয়েন্টগুলি 2 বারের পরিবর্তে 6 বার inc করা উচিত।

আপনি পরিবর্তিত পরীক্ষা বা অভ্যন্তরীণ লুপ দিয়ে পরীক্ষা যোগ করে সমান পারফরম্যান্স সম্পর্কে কিছুটা আস্থা অর্জনের চেষ্টা করতে পারেন get এটি দ্রুত:

func BenchmarkStringCheckNone4(b *testing.B) {
    c := 0
    b.ResetTimer()
    for n := 0; n < b.N; n++ {
            for _, _ = range ss {
                    c++
            }
    }
    t := len(ss) * b.N
    if c != t {
            b.Fatalf("did not catch empty strings: %d != %d", c, t)
    }
}

এটি দ্রুত নয়:

func BenchmarkStringCheckEq3(b *testing.B) {
    ss2 := make([]string, len(ss))
    prefix := "a"
    for i, _ := range ss {
            ss2[i] = prefix + ss[i]
    }
    c := 0
    b.ResetTimer()
    for n := 0; n < b.N; n++ {
            for _, s := range ss2 {
                    if s == prefix {
                            c++
                    }
            }
    }
    t := 2 * b.N
    if c != t {
            b.Fatalf("did not catch empty strings: %d != %d", c, t)
    }
}

উভয় রূপই প্রধান পরীক্ষার মধ্যে পার্থক্যের চেয়ে দ্রুত বা ধীর হয়।

প্রাসঙ্গিক বিতরণ সহ স্ট্রিং জেনারেটর ব্যবহার করে পরীক্ষার স্ট্রিং (গুলি) তৈরি করা ভাল। এবং পরিবর্তনশীল দৈর্ঘ্য আছে।

সুতরাং চলতে ফাঁকা স্ট্রিং পরীক্ষা করার জন্য প্রধান পদ্ধতির মধ্যে পারফরম্যান্স পার্থক্যের কোনও আত্মবিশ্বাস আমার নেই।

এবং আমি কিছুটা আত্মবিশ্বাসের সাথে বলতে পারি, খালি স্ট্রিংটি টেস্ট খালি স্ট্রিংয়ের চেয়ে খালি স্ট্রিংটি না পরীক্ষা করা দ্রুত। এবং 1 টি স্ট্রিং (উপসর্গের বৈকল্পিক) পরীক্ষা করার চেয়ে খালি স্ট্রিংটি পরীক্ষা করা আরও দ্রুত।


0

অফিসিয়াল গাইডলাইন অনুসারে এবং পারফরম্যান্সের দৃষ্টিকোণ থেকে এগুলি সমতুল্য উপস্থিত হয় ( এ্যানিসাস উত্তর ), সিন্টেক্সটিক্যাল সুবিধার কারণে s! = "" ভাল হবে। s! = "" সংকলনের সময় ব্যর্থ হবে যদি ভেরিয়েবলটি স্ট্রিং না হয় তবে লেন (গুলি) == 0 অন্যান্য কয়েকটি ডেটা ধরণের জন্য পাস করবে।


এমন একটি সময় ছিল যখন আমি সিপিইউ চক্র গণনা করি এবং এসেম্ব্লারকে পর্যালোচনা করি যে সি সংকলক সি এবং প্যাস্কাল স্ট্রিংগুলির কাঠামো তৈরি করেছিল এবং গভীরভাবে বুঝতে পেরেছিল ... এমনকি বিশ্বের সমস্ত অপটিমাইজেশনের সাথে len()কেবল সামান্য অতিরিক্ত অতিরিক্ত কাজ প্রয়োজন requires যাইহোক, আমরা সিতে যে জিনিসটি ব্যবহার করতাম সেটিকে বাম দিকটি একটিতে ফেলে দেওয়া হয়েছিল constবা s == "" s = "" হওয়া থেকে রোধ করতে অপারেটরের বাম দিকে স্থিতিযুক্ত স্ট্রিং লাগানো ছিল যা সি বাক্য গঠনতে গ্রহণযোগ্য। .. এবং সম্ভবত গোলংও। (প্রসারিত যদি দেখুন)
রিচার্ড

-1

পুরো স্ট্রিংটি ছাঁটাইয়ের চেয়ে এটি আরও পারফরম্যান্স হতে পারে, যেহেতু আপনাকে কেবল কমপক্ষে একটি অ-স্থান অক্ষর বিদ্যমান আছে তা পরীক্ষা করতে হবে

// Strempty checks whether string contains only whitespace or not
func Strempty(s string) bool {
    if len(s) == 0 {
        return true
    }

    r := []rune(s)
    l := len(r)

    for l > 0 {
        l--
        if !unicode.IsSpace(r[l]) {
            return false
        }
    }

    return true
}

3
@ রিচার্ড এটি হতে পারে, তবে "গোলং চেক স্ট্রিং ফাঁকা কিনা" বা গুগলিংয়ের জন্য গুগলিংয়ের সময়, এই একমাত্র প্রশ্নটি আসে যা এই লোকদের পক্ষে এটি তাদের পক্ষে, যা করা নজিরবিহীন জিনিস নয় isn't স্ট্যাক এক্সচেঞ্জ
ব্রায়ান লেশম্যান

-1

আমি মনে করি সবচেয়ে ভাল উপায়টি ফাঁকা স্ট্রিংয়ের সাথে তুলনা করা

বেঞ্চমার্কস্ট্রিংচেক 1 ফাঁকা স্ট্রিং সহ চেক করছে

বেনমার্কস্ট্রিংচেক 2 লেন শূন্যের সাথে চেক করছে

আমি খালি এবং খালি খালি স্ট্রিং চেকিংয়ের সাথে চেক করি। আপনি দেখতে পাচ্ছেন যে একটি ফাঁকা স্ট্রিং দিয়ে চেক করা দ্রুত।

BenchmarkStringCheck1-4     2000000000           0.29 ns/op        0 B/op          0 allocs/op
BenchmarkStringCheck1-4     2000000000           0.30 ns/op        0 B/op          0 allocs/op


BenchmarkStringCheck2-4     2000000000           0.30 ns/op        0 B/op          0 allocs/op
BenchmarkStringCheck2-4     2000000000           0.31 ns/op        0 B/op          0 allocs/op

কোড

func BenchmarkStringCheck1(b *testing.B) {
    s := "Hello"
    b.ResetTimer()
    for n := 0; n < b.N; n++ {
        if s == "" {

        }
    }
}

func BenchmarkStringCheck2(b *testing.B) {
    s := "Hello"
    b.ResetTimer()
    for n := 0; n < b.N; n++ {
        if len(s) == 0 {

        }
    }
}

5
আমি এই প্রমাণ কিছুই মনে করি। যেহেতু আপনার কম্পিউটার পরীক্ষা করার সময় অন্যান্য জিনিসগুলি করে এবং পার্থক্যটি একে অপরের থেকে দ্রুত বলে বলা ছোট। এটি ইঙ্গিত করতে পারে যে উভয় ফাংশন একই কলটিতে সংকলিত হয়েছিল।
এসআর
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.