是否存在类似于Python的Easy String Splicing的Java?

时间:2013-06-25 21:21:48

标签: java python string

好的,我想知道的是有一种方法可以让Java执行Python在下面可以做的事情......

string_sample = "hello world"

string_sample[:-1]
>>> "hello world"

string_sample[-1]
>>> "d"

string_sample[3]
>>> "l"

因为在我看来Java让你为同样的结果工作(我特别需要每次使用2个数字而缺少-1表示最后一个字符)

String string_sample = "hello world";

string_sample.substring(0,string_sample.length()-1);
>>> "hello world"

string_sample.substringstring_sample.length()];
>>> "d"

string_sample.(3,4);
>>> "l"

我还没有在Java中使用数组/列表,所以真的希望Java比这更容易

编辑:修改了'i'对于string_sample [3]的'l'。好好发现Maroun!

8 个答案:

答案 0 :(得分:16)

很抱歉,Java的substring不像Python的切片表示法那么灵活。

特别是:

  • 你可以给它一个开头,或者开始和结束,但不仅仅是结束。 (此外,没有任何步骤,但你不要错过那么多。)
  • 负指数是一个错误,而不是从最后的计数。

您可以看到文档here

然而,自己写这个并不难:

public String slice_start(String s, int startIndex) {
    if (startIndex < 0) startIndex = s.length() + startIndex;
    return s.substring(startIndex);
}

public String slice_end(String s, int endIndex) {
    if (endIndex < 0) endIndex = s.length() + endIndex;
    return s.substring(0, endIndex);
}

public String slice_range(String s, int startIndex, int endIndex) {
    if (startIndex < 0) startIndex = s.length() + startIndex;
    if (endIndex < 0) endIndex = s.length() + endIndex;
    return s.substring(startIndex, endIndex);
}

将它们作为某些实用程序类的静态方法。

显然这与Python不完全相同,但它可能会处理您想要的所有情况,而且非常简单。如果你想处理其他边缘情况(包括步骤和传递切片等等),你可以添加你想要的任何其他代码;没有一点特别棘手。


其他序列基本相同,但您需要subSequence而不是substring。 (您也可以在字符串上使用subSequence,因为StringCharSequence。)

数组实际上根本不是一种序列;您需要编写显式创建新数组并复制子数组的代码。但它仍然没有那么复杂。


请注意,您可能希望查找已经为您完成此操作的库。此页面上的其他答案中至少有三个链接,这将使您的搜索更容易。 :)(你可能仍然想为自己做一次,只是为了理解这些库是如何工作的 - 但对于生产代码,我宁愿使用一个其他人已经想出并测试所有边缘情况而不是重新实现的库当他们陷入单元测试或现场错误时,他们会对他们进行处理......)

答案 1 :(得分:10)

Java Boon Slice Notation允许使用字符串,列表,集合,地图等所有这些。

许多语言都有切片表示法(Ruby,Groovy和Python)。 Boon将此添加到Java。

Boon有三个slc运营商: slc slc (仅限开始)和 slcEnd

使用Boon,您可以切割字符串,数组(原始和通用),列表,集合,树集,树映射等等。

切片符号 - 温和的介绍

boon slice运算符的工作方式类似于Python / Ruby切片表示法:

Ruby切片表示法

 arr = [1, 2, 3, 4, 5, 6]
 arr[2]    #=> 3
 arr[-3]   #=> 4
 arr[2, 3] #=> [3, 4, 5]
 arr[1..4] #=> [2, 3, 4, 5]

Python切片表示法

string = "foo bar" 
string [0:3]  #'foo'
string [-3:7] #'bar'

以下内容源于对Python的切片表示法的精彩编写:

切片表示法的基础知识如下:

Python切片表示法

     a[ index ]       # index of item
     a[ start : end ] # items start through end-1
     a[ start : ]     # items start through the rest of the array
     a[ : end ]       # items from the beginning through end-1
     a[ : ]           # a copy of the whole array

使用Boon的Java Slice表示法:

      idx( index )         // index of item
      slc( a, start, end ) // items start through end-1
      slc( a, start )      // items start through the rest of the array
      slcEnd( a, end )     // items from the beginning through end-1
      copy( a )            // a copy of the whole array

slc 代表切片 idx 代表索引 slcEnd 代表结束切片。 副本代表好,错误,当然是副本

要记住的关键点是结束值表示不在所选切片中的第一个值。因此,end和start之间的差异是所选元素的数量。 另一个特性是开始或结束可能是负数,这意味着它从数组的末尾而不是从开头开始计数。

因此:

带负面索引的Python切片表示法

         a[ -1 ]    # last item in the array
         a[ -2: ]   # last two items in the array
         a[ :-2 ]   # everything except the last two items

Java否定指数

         idx   ( a, -1)     // last item in the array
         slc   ( -2 )       // last two items in the array
         slcEnd( -2 )       // everything except the last two items

Python和Boon对程序员很友好,如果项目少于你要求的项目:Python不允许你超出界限,如果你这样做,则返回更糟糕的空列表。 Boon遵循这一传统,但提供了一个获得越界异常的选项(稍后描述)。在Python和Boon中,如果你走远,你得到的长度,如果你试图低于0你得到0(计算后低于0)。相反,Ruby会给你一个空指针(Nil)。 Boon复制Python风格,因为Boon的目标之一是避免返回null(你得到一个例外,Option)。 (Boon有第二个名为zlc的运算符抛出一个越界索引异常,但大多数人都应该使用slc。)

例如,如果您要求slcEnd(a,-2)(a [: - 2])并且只包含一个元素,则会得到一个空列表而不是错误。有时你更喜欢这个错误,而Boon你有这个选择。

更多切片

以下是一些基本的Java类型,列表,数组,素食,原始字符数组和原始字节数组。

声明要在Boon中使用的变量

//Boon works with lists, arrays, sets, maps, sorted maps, etc.
List<String> fruitList;
String [] fruitArray;
Set<String> veggiesSet;
char [] letters;
byte [] bytes;
NavigableMap <Integer, String> favoritesMap;
Map<String, Integer> map;

//In Java a TreeMap is a SortedMap and a NavigableMap by the way.
Boon附带了帮助方法,允许您轻松创建列表,集合,映射,并发映射,有序映射,有序集等。帮助方法是safeList,list,set,sortedSet,safeSet,safeSortedSet等。想法是让Java感觉更像列表,而地图是以类型构建的。

初始化set,list,字符串数组,字符数组和字节数组

veggiesSet  =  set( "salad", "broccoli", "spinach");
fruitList   =  list( "apple", "oranges", "pineapple");
fruitArray  =  array( "apple", "oranges", "pineapple");
letters     =  array( 'a', 'b', 'c');
bytes       =  array( new byte[]{0x1, 0x2, 0x3, 0x4});

甚至还有创建地图和有序地图的方法,称为map,sortedMap,safeMap(并发)和sortedSafeMap(并发)。这些主要是因为Java没有列表,地图等的文字。

Java:使用map运算符生成SortedMap和Map

 favoritesMap = sortedMap(
      2, "pineapple",
      1, "oranges",
      3, "apple"
 );


 map =    map (
    "pineapple",  2,
    "oranges",    1,
    "apple",      3
 );

您可以使用idx运算符索引地图,列表,数组等。

Java:使用Boon Java idx运算符获取索引值

 //Using idx to access a value.

 assert idx( veggiesSet, "b").equals("broccoli");

 assert idx( fruitList, 1 ).equals("oranges");

 assert idx( fruitArray, 1 ).equals("oranges");

 assert idx( letters, 1 ) == 'b';

 assert idx( bytes, 1 )      == 0x2;

 assert idx( favoritesMap, 2 ).equals("pineapple");

 assert idx( map, "pineapple" )  == 2;

idx运算符也适用于负索引。

Java:使用带负值的idx运算符

         //Negative indexes

          assert idx( fruitList, -2 ).equals("oranges");

          assert idx( fruitArray, -2 ).equals("oranges");

          assert idx( letters, -2 ) == 'b';

          assert idx( bytes, -3 )   == 0x2;

Ruby,Groovy和Python都有这个功能。现在你也可以在Java中使用它! Java版本(Boon)与原始数组一起使用,因此你得到 no auto-boxing

Ruby和Python不具备的是SortedSets和SortedMaps的切片表示法。 您可以使用切片表示法在Java中搜索已排序的地图和已排序的集合

切片表示法适用于有序地图和有序集。

这是一个将几个概念放在一起的例子。

          set = sortedSet("apple", "kiwi", "oranges", "pears", "pineapple")

          slcEnd( set, "o" )      //returns ("oranges", "pears", "pineapple")
          slc( set, "ap", "o" )   //returns ("apple", "kiwi"),
          slc( set, "o" )         //returns ("apple", "kiwi")

您实际上是在对有序映射进行切片,而有序集是在各种查询之间进行的。 什么项目&#34; pi&#34;?

          after(set, "pi") //pineapple

在菠萝之前?

          before(set, "pi")

好的,请一步一步地完成它....

  NavigableSet<String> set =
          sortedSet("apple", "kiwi", "oranges", "pears", "pineapple");

  assertEquals(

          "oranges", idx(set, "ora")

  );

请记住:TreeSet实现了NavigableSet和SortedSet。

这来自我的博客......

http://rick-hightower.blogspot.com/2013/10/java-slice-notation-to-split-up-strings.html

有更多的例子。

我从Python切片的讨论中得到了一些措辞。

Explain Python's slice notation

这是Boon项目链接:

https://github.com/RichardHightower/boon

现在让我们继续SLICE!

我们可以查看以&#39; o&#39;开头的集合中的第一个水果。使用:

idx(set, "o")

这是我们之前创建的一组水果(set是一个TreeSet,带有&#34; apple&#34;,&#34; kiwi&#34;, &#34;橘子&#34;,&#34;梨&#34;,&#34;菠萝&#34;在它)。

      assertEquals(

          "oranges", idx(set, "o")

      );

我们找到了橘子!

这里又是一次,但这一次我们正在寻找以&#34; p&#34;开头的水果,即idx(set,&#34; p&#34;)。

      assertEquals(
          "pears",
          idx(set, "p")
      );

呀!我们找到了梨!

以&#34; pi&#34;开头的水果怎么样?喜欢&#34;菠萝&#34; - idx(设置,&#34; pi&#34;)

  assertEquals(
          "pineapple",
          idx(set, "pi")
  );

您还可以要求在另一个项目之后的项目。什么是&#34; pi&#34;? 之后(设置,&#34; pi&#34;)

  assertEquals(

          "pineapple",
          after(set, "pi")

  );

&#34;菠萝&#34;在项目&#34; pi&#34;之后。之后和idx是一样的。那我为什么要添加一个?所以我以前可以有!!! :) 如果您想知道之前的内容&#34; pi&#34;?

,该怎么办?

之前(设置,&#34; pi&#34;)

  assertEquals(

          "pears",
          before(set, "pi")

  );

&#34; ap&#34;之间的所有水果怎么样?和&#34; o&#34;?正如我所承诺的那样有切片符号!

slc(设置,&#34; ap&#34;,&#34; o&#34;)

  assertEquals(

          sortedSet("apple", "kiwi"),
          slc(set, "ap", "o")

  );

&#34; o&#34;?

之后的所有水果怎么样?

slc(设置,&#34; o&#34;)

  assertEquals(

          sortedSet("apple", "kiwi"),
          slc(set, "o")

  );

所以所有水果都在&#34; o&#34;是&#34; apple&#34;和&#34; kiwi&#34;。

所有水果怎么样?&#34; o&#34;? (slcEnd读到它,因为我正在切断结束。)

slcEnd(设置,&#34; o&#34;)

  assertEquals(

          sortedSet("oranges", "pears", "pineapple"),
          slcEnd(set, "o")
  );

所有水果都包括在内,包括&#34; o&#34;是&#34;橙子&#34;,&#34;梨&#34;和&#34;菠萝&#34;。

像列表一样安全切片

如果索引超出范围,这些运算符会抛出异常:

使用Boon

Java Slice表示法如下:

      ix( index )         // index of item
      zlc( a, start, end ) // items start through end-1
      zlc( a, start )      // items start through the rest of the array
      zlcEnd( a, end )     // items from the beginning through end-1

zlc 代表零容差切片 ix 代表零容忍指数 zlcEnd 代表零容差结束切片。 副本代表好,错误,当然是副本

男孩和女孩......记得要经常使用你不了解的物品进行安全切片。

也适用于原语,所以没有自动装箱

索引原语

 byte[] letters =
      array((byte)'a', (byte)'b', (byte)'c', (byte)'d');

 assertEquals(
      'a',
      idx(letters, 0)
 );


 assertEquals(
      'd',
      idx(letters, -1)
 );


 assertEquals(
      'd',
      idx(letters, letters.length - 1)
 );

 idx(letters, 1, (byte)'z');

 assertEquals(
      (byte)'z',
      idx(letters, 1)
 );

方法len和idx是通用运算符,它们可用于列表,数组,集合,映射等。

len 给我一个类似数组,类似列表的地图长度的东西。 idx 在&#34;索引&#34;的位置给我这个项目在类似数组,类似列表的地图中。

HOME MC String Slice!

以下是Boon Java String Slicing的一些示例

  String letters = "abcd";

  boolean worked = true;

  worked &=

          idx(letters, 0)  == 'a'
                  || die("0 index is equal to a");



  worked &=

          idx(letters, -1)  == 'd'
                  || die("-1 index is equal to a");

表达idx的另一种方式(字母,-1)==&#39; d&#39;是idx(letters,letters.length() - 1)==&#39; d&#39;! 我更喜欢较短的方式!

  worked &=

          idx(letters, letters.length() - 1) == 'd'
                   || die("another way to express what the -1 means");


  //We can modify too
  letters = idx(letters, 1, 'z');

  worked &=

          idx(letters, 1) == 'z'
                  || die("Set the 1 index of letters to 'z'");


  worked &= (
          in('a', letters) &&
          in('z', letters)
  ) || die("'z' is in letters and 'a' is in letters");

Slice Slice Baby!

  letters = "abcd";

  worked &=
          slc(letters, 0, 2).equals("ab")
              || die("index 0 through index 2 is equal to 'ab'");



  worked &=
          slc(letters, 1, -1).equals("bc")
                  || die("index 1 through index (length -1) is equal to 'bc'");


  worked &=
          slcEnd(letters, -2).equals("ab")
                  || die("Slice of the end of the string!");


  worked &=
          slcEnd(letters, 2).equals("ab")
                  || die("Vanilla Slice Slice baby!");

滚动我的5.0,让我的抹布自上而下让我的头发可以吹! Slice Slice Baby !!!

答案 2 :(得分:7)

Apache commons-lang对此in StringUtils有一些支持:

  

从指定的String中获取子字符串,避免异常。

     

负起始位置可用于从字符串

的末尾开始n个字符

你仍然需要使用显式的起始索引。

答案 3 :(得分:1)

您可以轻松编写这样的方法,请记住从字符串的长度中减去负索引以获得正确的索引。

public String slice(String s, int start) {
   if (start < 0) start = s.length() + start; 

   return s.substring(start);
}

答案 4 :(得分:1)

使用substring

class Main
{
  public static void main (String[] args) throws java.lang.Exception
  {
     String s = new String("hello world");
     System.out.println(s.substring(0, s.length()));
     System.out.println(s.substring(s.length() - 1, s.length()));
     System.out.println(s.substring(3, 4));
  }
}

charAt

System.out.println(s.charAt(s.length() - 1));
System.out.println(s.charAt(3));

Java不是python,因此应该避免使用负面索引来保持稳定性。但是,您可以创建一个简单的转换函数。

答案 5 :(得分:0)

我认为没有这样的Java字符串库提供与python提供的完全相同的东西。您可以做的最好的事情就是构建一个提供所需功能的新类。由于java中的String是一个最后一个类,你不能从中扩展类,你需要使用组合。例如:

public class PythonString {
  protected String value;
  public PythonString(String str) {
    value = new String(str);
  }

  public char charAt(int index) {
    if (index < 0) {
      return value.charAt(value.length() + index);
    }
    return value.charAt(index);
  }

  ....

}

另一种方法是创建一个静态字符串库。

答案 6 :(得分:0)

我为它创建了一个简单的库,名为JavaSlice,它提供了一种统一的方式来访问Java中的String,List或数组,与Python类似。

因此,您的示例将简单地写为:

    String sample = "hello world";

    System.out.println(slice(sample, 0, -1)); // "hello worl"
    System.out.println(slice(sample, -1)); // 'd'
    System.out.println(slice(sample, 3)); // 'l'

答案 7 :(得分:-1)

简单回答,没有。字符串在两种语言中都是不可变的。字符串在内部存储为字符数组,因此使用子字符串并使用Python中的括号基本上做同样的事情。 Java不支持运算符重载,因此无法为该语言提供该功能。使用子字符串并不是那么糟糕。你不应该经常这样做。如果你经常这样做以简化你的使用,你总是可以编写辅助函数。