2011-01-19 31 views
7

Đây là một phiên bản sử dụng tôi đã viết chia:biểu Scala để thay thế một phần mở rộng tập tin trong một chuỗi

fileName.split('.').init ++ Seq("js") mkString "." 

này biến đổi ví dụ foo.bar.coffee vào foo.bar.js.

Những gì tôi thích:

  • nó hoạt động
  • nó không dựa trên những thứ như indexOf()
  • nó cảm thấy chức năng;)

Những gì tôi không thích:

  • không ngắn như tôi mong đợi
  • nó có thể gây nhầm lẫn cho một số độc giả

Làm cách nào để viết phiên bản đơn giản/đơn giản hơn?

CẬP NHẬT: Câu trả lời tuyệt vời bên dưới! Nói tóm lại:

  • có vẻ như cách tiếp cận ban đầu của tôi ở trên là không xấu mặc dù nó không bao gồm một số trường hợp góc, nhưng đó là fixable với một biểu thức lâu hơn nếu bạn cần để trang trải những
  • khác, cách tiếp cận hơi ngắn hơn sử dụng regexps, mà sẽ được nhiều hơn hoặc ít có thể đọc tùy thuộc vào nền regexp của bạn
  • một cú pháp hơi ngắn hơn cho cách tiếp cận ban đầu (trường hợp góc không được đề cập) lần đọc:

    fileName.split('.').init :+ "js" mkString "."

+2

Đối với hồ sơ, điều này rất đơn giản với tôi. –

+1

Tôi đồng ý với Rafe. Cá nhân tôi thích nó tốt hơn so với các phiên bản biểu thức thông thường. Tuy nhiên, nó không hoạt động tốt với các tên tệp không có phần mở rộng. Bạn có thể loại bỏ '++ Seq (" js ")' bằng cách thay thế nó bằng ': +" js "', nhân tiện. – Madoc

+0

Hãy nhớ rằng tùy thuộc vào những gì bạn muốn làm, các tệp có tiện ích mở rộng đôi không được xử lý "chính xác", ví dụ: 'x.tar.gz' trở thành' x.tar.js' – Raphael

Trả lời

9

Tôi sợ bạn thực sự phải làm cho nó còn để làm những gì có lẽ là điều mạnh mẽ hợp lý nhất:

scala> "oops".split('.').init ++ Seq("js") mkString "." 
res0: String = js 

Kinda bất ngờ để mất tên của tập tin của bạn (ít nhất là nếu bạn' một người dùng cuối)!

Hãy thử regex:

scala> "oops".replaceAll("\\.[^.]*$", ".js") 
res1: java.lang.String = oops 

Không mất tên tập tin, nhưng không có phần mở rộng trong hai. Ack.

Hãy khắc phục nó:

def extensor(orig: String, ext: String) = (orig.split('.') match { 
    case xs @ Array(x) => xs 
    case y => y.init 
}) :+ "js" mkString "." 

scala> extensor("oops","js") 
res2: String = oops.js 

scala> extensor("oops.txt","js") 
res3: String = oops.js 

scala> extensor("oops...um...","js") 
res4: String = oops...js 

Hoặc với regex:

scala> "oops".replaceAll("\\.[^.]*$", "") + ".js" 
res5: java.lang.String = oops.js 

scala> "oops.txt".replaceAll("\\.[^.]*$", "") + ".js" 
res6: java.lang.String = oops.js 

scala> "oops...um...".replaceAll("\\.[^.]*$", "") + ".js" 
res7: java.lang.String = oops...um...js 

(Lưu ý các hành vi khác nhau về vụ việc góc nơi tên tập tin kết thúc với giai đoạn.)

+0

Những gì tôi thấy là một sự lãng phí là tất cả các chất nền cho các phần được phân định theo thời gian của tên tệp đang được tạo và sau đó được nối lại. Để tránh điều này, nó sẽ là tốt để sử dụng 'lastIndexOf', mà OP không thích. Tuy nhiên, tôi nghĩ đó sẽ là một ý kiến ​​hay. – Madoc

+0

@Madoc - Có lẽ bạn đang thực hiện các thao tác này vì bạn muốn làm việc với các tệp. Một hoạt động tệp điển hình mất bao lâu để so sánh với một phân tách + mkString? –

+0

Tôi hy vọng VM sẽ tối ưu hóa điều này. – Raphael

3

Liệu thay thế regex đơn giản có thực hiện thủ thuật không?

Giống như:

scala> "package.file.java".replaceAll("(\\.[^\\.]*$)", ".rb") 
scala> "package.file.rb" 
+0

Haha, xin chào Eric. Bạn có 12 giây trên tôi, nhưng tôi là 2 ký tự ngắn hơn. ;) – Synesso

+0

Tôi biết mình phải cải thiện regex của mình, ... – Eric

2

Bạn luôn có thể sử dụng phương pháp replaceAll trên java.lang.String

scala> "foo.bar.coffee".replaceAll("\\.[^.]*$", ".js") 
res11: java.lang.String = foo.bar.js 

Đó là ngắn hơn nhưng ít có thể đọc được.

2

Có gì sai với lastIndexOf?

fileName.take(1 + fileName.lastIndexOf(".")) + "js" 

Tất nhiên nếu bạn muốn giữ fileName khi nó không chứa bất kỳ dấu chấm, bạn cần phải làm nhiều hơn một chút

(if (fileName.contains('.')) fileName.take(fileName.lastIndexOf(".")) 
else fileName) + ".js" 
+0

Không có gì hoàn toàn sai với chỉ mục. Nhưng về bản chất tôi đã cố gắng để xem nơi các phương pháp tiếp cận khác dẫn bạn. Nó giống như sự khác biệt giữa việc sử dụng 'for (i = 0; i ebruchez

2

Vì vậy, tôi sẽ đi cho tốc độ ở đây. Khi điều đó xảy ra, substring là thời gian không đổi bởi vì nó chỉ đơn giản là không sao chép chuỗi. Vì vậy,

((index: Int) => (
) + ".js")(fileName lastIndexOf '.') 

Điều này sử dụng đóng cửa, điều này sẽ làm chậm xuống một chút. Nhanh hơn:

def addJS(fileName: String) = { 
    def addJSAt(index: Int) = (
     if (index >= 0) fileName substring (0, index) 
     else fileName 
    ) + ".js" 

    addJSAt(fileName lastIndexOf '.') 
} 

EDIT: Vì nó xảy ra, Java bây giờ không sao chép các chuỗi trên substring.

+0

Đã xảy ra sự cố khi bạn đang sử dụng tốc độ và tôi đang viết các mẫu phù hợp và nói đừng lo lắng .... –

+0

@Rex Hey, không giống như bạn để lại cho tôi bất kỳ thứ gì khác để đi ... :-) –

+0

I biết điều này là cổ đại, chỉ cần tự hỏi nếu có hiệu suất hoặc lý do khác để sử dụng một hàm lồng nhau hơn là một cái gì đó như 'def addJS (fileName: String) = { val index = fileName lastIndexOf '.' (nếu (chỉ số> = 0) tên tệp tin chuỗi con (0, chỉ mục) else tên tệp ) + ".js" } ' – Davos

2

Rất dễ dàng với lastIndexOf, và làm việc với tên file có chứa nhiều hơn một dấu chấm

def getFileNameWithoutExtension(fileName: String): String = { 
    fileName.dropRight(fileName.length - fileName.lastIndexOf(".")) 
} 

val fileName = "foo.bar.coffee" 

getFileNameWithoutExtension(fileName) + ".js" 

Kết quả là foo.bar.js

Các vấn đề liên quan