การแยกสตริงว่างจะส่งกลับอาร์เรย์ขนาด 1:
scala> "".split(',')
res1: Array[String] = Array("")
พิจารณาว่าสิ่งนี้ส่งคืนอาร์เรย์ว่าง:
scala> ",,,,".split(',')
res2: Array[String] = Array()
กรุณาอธิบาย :)
การแยกสตริงว่างจะส่งกลับอาร์เรย์ขนาด 1:
scala> "".split(',')
res1: Array[String] = Array("")
พิจารณาว่าสิ่งนี้ส่งคืนอาร์เรย์ว่าง:
scala> ",,,,".split(',')
res2: Array[String] = Array()
กรุณาอธิบาย :)
คำตอบ:
ด้วยเหตุผลเดียวกันว่า
",test" split ','
และ
",test," split ','
จะส่งคืนอาร์เรย์ขนาด 2 ทุกอย่างก่อนที่การจับคู่แรกจะถูกส่งกลับเป็นองค์ประกอบแรก
"".split("wtf").length
จะส่งกลับ 0 เฉพาะใน JS เท่านั้น: /
"," split ","
ส่งกลับอาร์เรย์เป็น 0
ถ้าคุณแบ่งส้มเป็นศูนย์คุณจะมีชิ้นเดียว - สีส้ม
"orange".split(',')
แต่ไม่ชัดเจนว่าเกี่ยวข้องกับการแยกสตริงว่างเปล่า ถ้าฉันแยกการขาดสีส้มเป็นศูนย์ครั้งฉันก็ยังไม่มีสีส้ม เราแสดงว่าเป็นรายการที่ไม่มีส้มรายการหนึ่งไม่มีส้มรายการส้มสิบสองผลหรืออะไร ไม่ใช่คำถามว่าเราลงเอยด้วยอะไร แต่เราเป็นตัวแทนของมันอย่างไร
วิธีการแยก Java และ Scala ทำงานในสองขั้นตอนดังนี้:
",,,".split(",")
ส่งคืนอาร์เรย์ว่างตามนี้ผลลัพธ์ของ"".split(",")
ควรจะเป็นอาร์เรย์ว่างเนื่องจากขั้นตอนที่สองใช่ไหม?
มันควรจะ. น่าเสียดายที่นี่เป็นเคสเข้ามุมที่นำมาใช้โดยเทียม และนั่นเป็นสิ่งที่ไม่ดี แต่อย่างน้อยก็มีการบันทึกไว้java.util.regex.Pattern
หากคุณจำไว้ว่าให้ดูเอกสาร:
สำหรับ n == 0 ผลลัพธ์จะเป็นสำหรับ n <0 ยกเว้นสตริงว่างที่ต่อท้ายจะไม่ถูกส่งกลับ (โปรดทราบว่ากรณีที่อินพุตเป็นสตริงว่างนั้นเป็นแบบพิเศษตามที่อธิบายไว้ข้างต้นและพารามิเตอร์ขีด จำกัด จะไม่ใช้ที่นั่น)
ดังนั้นฉันขอแนะนำให้คุณส่งผ่านn == -1
เป็นพารามิเตอร์ที่สองเสมอ(ซึ่งจะข้ามขั้นตอนที่สองด้านบน) เว้นแต่คุณจะทราบโดยเฉพาะว่าคุณต้องการบรรลุอะไร / คุณแน่ใจว่าสตริงว่างไม่ใช่สิ่งที่โปรแกรมของคุณจะได้รับเป็นอินพุต
หากคุณใช้ Guava ในโปรเจ็กต์ของคุณอยู่แล้วคุณสามารถลองใช้คลาสSplitter (เอกสารประกอบ) มี API ที่สมบูรณ์มากและทำให้โค้ดของคุณเข้าใจง่ายมาก
Splitter.on(".").split(".a.b.c.") // "", "a", "b", "c", ""
Splitter.on(",").omitEmptyStrings().split("a,,b,,c") // "a", "b", "c"
Splitter.on(CharMatcher.anyOf(",.")).split("a,b.c") // "a", "b", "c"
Splitter.onPattern("=>?").split("a=b=>c") // "a", "b", "c"
Splitter.on(",").limit(2).split("a,b,c") // "a", "b,c"
"".split (",", n)
สร้างอาร์เรย์องค์ประกอบหนึ่งรายการสำหรับ n in (-1, 0, 1) ด้วย Oracle JDK 8 จะเป็นการดีที่จะได้รับรายการโทเค็นที่ไม่ว่างเปล่าเท่านั้น - เดาว่าอาจจำเป็นต้องใช้ regex แบบเต็ม (บางอย่างเช่น"[^,\\s]+[^,]*[^,\\s]*"
)
การแยกสตริงว่างจะส่งคืนสตริงว่างเป็นองค์ประกอบแรก หากไม่พบตัวคั่นในสตริงเป้าหมายคุณจะได้รับอาร์เรย์ขนาด 1 ที่เก็บสตริงเดิมแม้ว่าจะว่างเปล่าก็ตาม
",".split(",")
ส่งคืนอาร์เรย์ว่าง
"a".split(",")
-> "a"
ดังนั้น
"".split(",")
->""
",".split(",")
ส่งคืนอาร์เรย์ว่าง
ในภาษาโปรแกรมทั้งหมดฉันรู้ว่าสตริงว่างยังคงเป็นสตริงที่ถูกต้อง ดังนั้นการแยกโดยใช้ตัวคั่นใด ๆ จะส่งคืนอาร์เรย์องค์ประกอบเดียวเสมอโดยที่องค์ประกอบนั้นเป็นสตริงว่าง หากเป็นสตริงว่าง (ไม่ว่าง) นั่นจะเป็นปัญหาอื่น
นี้split
พฤติกรรมที่จะรับมาจาก Java สำหรับดีขึ้นหรือแย่ลง ...
Scala ไม่แทนที่คำนิยามจากString
ดั้งเดิม
โปรดทราบว่าคุณสามารถใช้limit
อาร์กิวเมนต์เพื่อแก้ไขลักษณะการทำงาน :
พารามิเตอร์ขีด จำกัด ควบคุมจำนวนครั้งที่ใช้รูปแบบดังนั้นจึงมีผลต่อความยาวของอาร์เรย์ผลลัพธ์ ถ้าขีด จำกัด n มีค่ามากกว่าศูนย์รูปแบบจะถูกนำไปใช้มากที่สุด n - 1 เท่าความยาวของอาร์เรย์จะไม่เกิน n และรายการสุดท้ายของอาร์เรย์จะมีอินพุตทั้งหมดที่อยู่นอกเหนือจากตัวคั่นที่ตรงกันล่าสุด ถ้า n ไม่เป็นค่าบวกรูปแบบจะถูกนำไปใช้กี่ครั้งก็ได้และอาร์เรย์จะมีความยาวเท่าใดก็ได้ ถ้า n เป็นศูนย์รูปแบบจะถูกนำไปใช้กี่ครั้งก็ได้อาร์เรย์สามารถมีความยาวเท่าใดก็ได้และการต่อท้ายสตริงว่างจะถูกทิ้ง
กล่าวคือคุณสามารถตั้งค่าlimit=-1
ให้รับพฤติกรรมของ (ทั้งหมด?) ภาษาอื่น:
@ ",a,,b,,".split(",")
res1: Array[String] = Array("", "a", "", "b")
@ ",a,,b,,".split(",", -1) // limit=-1
res2: Array[String] = Array("", "a", "", "b", "", "")
ดูเหมือนว่าจะเป็นที่รู้จักกันดีว่าพฤติกรรมของ Java ค่อนข้างสับสนแต่:
พฤติกรรมข้างต้นสามารถสังเกตได้ตั้งแต่ Java 5 ถึง Java 8 เป็นอย่างน้อย
มีความพยายามที่จะเปลี่ยนพฤติกรรมเพื่อกลับอาร์เรย์ที่ว่างเปล่าคือเมื่อแยกสตริงที่ว่างเปล่าในJDK-6559590 อย่างไรก็ตามในไม่ช้ามันก็ถูกเปลี่ยนกลับในJDK-8028321เมื่อมันทำให้เกิดการถดถอยในที่ต่างๆ การเปลี่ยนแปลงนี้ไม่เคยทำให้เป็นรุ่น Java 8 เริ่มต้น
หมายเหตุ: วิธีการแบ่งไม่ได้อยู่ใน Java ตั้งแต่ต้น ( ไม่ใช่ใน 1.0.2 ) แต่จริงๆแล้วมีตั้งแต่อย่างน้อย 1.4 (เช่นดูJSR51ประมาณปี 2545) ฉันยังคงตรวจสอบ ...
อะไรคือเหตุผลที่ชัดเจน Java เลือกนี้ในสถานที่แรก (ความสงสัยของผมก็คือว่ามันเดิมกำกับดูแล / ข้อผิดพลาดในกรณี "ขอบ") แต่ตอนนี้อบถาวรเป็นภาษาและอื่น ๆก็ยังคง
"".split(",")
[""]
สตริงว่างไม่มีสถานะพิเศษในขณะที่แยกสตริง คุณสามารถใช้:
Some(str)
.filter(_ != "")
.map(_.split(","))
.getOrElse(Array())