Рассмотрим список Ls из URL всех веб-страниц на данном сайте, т. е. все URL-адреса в списке имеют один и тот же префикс домена (например, http://www.fancysite.com). Остальная часть каждого URL-адреса после удаления префикса представляет собой последовательность строк, разделенных /b то есть в форме /abc/xyz/pqs/.../lmn.html.
Задача, которую необходимо решить, состоит в том, чтобы вычислить количество URL-адресов в Ls на заданном уровне. Уровень определяется по количеству косых черт (например, /b символов) в URL-адресе после удаления префикса общего домена. Например, http://www.fancysite.com находится в level 0, http://www.fancysite.com/xyz/xyz.html находится в level 2 и так далее. Вы можете предположить, что URL-адреса в Ls уникальны (т. е. Ls не имеют дубликатов).
Для вышеуказанного вопроса я написал следующий код ниже:
List<String> ls = new ArrayList<>();
for(String url : ls){
String [] parts = url.split(https://www.fancysite.com);
int count=0;
for(int i=0; i<=parts[1].length(); i++){
if (parts[1].charAt(i)== “/“){
count++;
}
S.O.P(“Level of this particular url is”+ count;
}
}
Любой комментарий/обновление/подход будет оценен
A level is counted by the number of slashes Путь может заканчиваться косой чертой, но если после косой черты ничего нет, я не думаю, что это должно увеличивать «уровень» количества путей.
@markspace кажется, что путь каждый раз будет заканчиваться .html .. поэтому в URL-адресе учитываются только необходимые косые черты.




Я придумал это решение:
public static void main(String[] args) throws MalformedURLException {
List<String> ls = new ArrayList<>();
ls.add("https://example.com");
ls.add("https://example.com/one");
ls.add("https://example.com/two");
ls.add("https://example.com/one/three");
ls.add("https://example.com/one/one");
ls.add("https://example.com/one/two");
Map<Integer, List<URL>> levelToUrls = new HashMap<>();
for(String urlRaw : ls){
URL url = new URL(urlRaw);
String path = url.getPath();
String[] splitedPath = path.split("/");
levelToUrls.computeIfAbsent(splitedPath.length - 1, integer -> new LinkedList<>()).add(url);
}
levelToUrls.forEach((integer, urls) -> System.out.println("Level " + integer + " How many : " + urls.size()));
}
Это выводит:
Level 0 How many : 1
Level 1 How many : 2
Level 2 How many : 3
В основном я использую карту для хранения списка URL-адресов, сопоставленных с соответствующим уровнем, однако Map<Integer, Integer> также будет достаточно, если вы не хотите иметь доступ к URL-адресам по уровню.
Тот же результат с использованием потоков Java 8:
Map<Integer, Long> levelToUrlCount = ls.stream()
.map(s -> s.split("/").length - 3)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
levelToUrlCount.forEach((level, howMany) -> System.out.println("Level " + level + " How many : " + howMany));
Ваш подход кажется хорошим, но мне нужен результат, поскольку каждый URL-адрес с выходом соответствующего уровня!
У вас есть данные на карте, поэтому вы можете делать что угодно с данными, хранящимися на карте. Теперь эта карта сопоставляет уровень со списком URL-адресов.
Один лайнер:
final String URL = "https://example.com/one/two";
long level = URL.chars().filter(ch -> ch == '/').count() - 2;
Здесь мы подсчитываем количество косых черт / в строке, а затем вычитаем 2 из исходного количества косых черт после https.
Разместите это в Обзор кода вместо этого